9. 主从复制怎么做到的
Last updated
Was this helpful?
Last updated
Was this helpful?
上图有一个主节点以及一个从节点, 主节点要做的事情非常简单, 只要将自己的写操作记录到Binary Log里面即可, 从节点需要有两个线程, 来完成两件事:
一个IO线程, 负责到主节点里拉binlog来, 拉过来的binlog本质上是一个个的sql语句, 先暂时存到自己的Relay Log里去
另一个SQL线程, 负责从RelayLog里把SQL语句取出来并执行, 主节点的所有写操作在从节点中都能被执行到, 从而保证了主从的一致性
如果仔细想想就会觉得这其中有问题, 主从同步总是有时间差的, 有没有可能主节点都已经commit了, 但是从节点都还没收到这条消息? 这样搞下去延迟都是小事, 但如果主节点永久性的crash了, 是不是说从节点永远都不会有这条记录了? 即使它已经commit了?
这种主从一致性的问题, 于是我们想到了raft协议, 在raft里只有半数以上的从节点ACK(日志已记录)了, 这条消息才能被commit了, 我们有没有办法把这种思路也给带过来呢?
我们现在要求主节点commit之前必须要求, 大家都要执行这条记录才行, 这种方法叫做半同步复制, 稳吗? 比以前稳, 但还不够稳
所有的从节点都已经同步过binlog了 - 半同步模式
只要有一个从节点复制过binglog就行 - 全同步模式
MySQL的commit叫二段式提交, 在你点击提交这个按钮以后, 先记录binlog, 然后再到引擎层提交事务(二段). 正常情况下一切都没有问题, 但主机宕机了, 重启后就会进入恢复阶段, 先读取redolog发现这个事务没提交, 那这个事务应该回滚吗? 不确定先挂着, 看看binlog, 只要binlog里存在那么就认为要提交.
再回头看看这种提交方式带来的问题, 假设主机现在准备提交, 按照半同步复制的要求, 我们记录binlog并同步给从节点, 然而还没同步就挂了, 那么备机的relaylog里是没有这个事务的. 然后备机成为主机, 在原主机恢复以后就会检查自己的binlog, 发现有, 然后就要执行, 这一执行就会直接导致主从数据永久的不一致, 非常的蛋疼!!
也是有的, 这里面唯一的问题就是主从的binlog没有同步搞出来的, 我听说阿里搞出了一个"MySQL金融版", 在一个节点加入集群之前, 通过raft协议同步集群内的binlog, 这样就可以避免以上的问题