MySQL主从同步原理

99 阅读7分钟

主从同步原理

①客户端将写入数据的需求交给主节点,主节点先向自身写入数据。

②数据写入完成后,紧接着会再去记录一份Bin-log二进制日志。

③配置主从架构后,主节点上会创建一条专门监听Bin-log日志的log dump线程。

④当log dump线程监听到日志发生变更时,会通知从节点来拉取数据。

⑤从节点会有专门的I/O线程用于等待主节点的通知,当收到通知时会去请求一定范围的数据。

⑥当从节点在主节点上请求到一定数据后,接着会将得到的数据写入到relay-log中继日志。

⑦从节点上也会有专门负责监听relay-log变更的SQL线程,当日志出现变更时会开始工作。

⑧中继日志出现变更后,接着会从中读取日志记录,然后解析日志并将数据写入到自身磁盘中。

异步复制(默认)

master只负责写Binlog和返回结果,至于Binlog有没有被读取和重放,它是不关心的,那么这就可能就发生主从延迟的问题。或者master宕机后,slave升级为master,但是binlog未执行完毕,就会导致数据不一致。

同步复制

当主节点接收到一个客户端的写请求后,先会往自身写入数据,接着会去要求其他从节点也写入数据,当所有从节点的数据写入完成后,最终才会向客户端返回写入成功。

虽然同步复制的模式能够确保数据的强一致性,但由于其太影响写入效率,因此很少有主从机制会采用这种模式同步数据,包括MySQL默认也是采用异步复制方案,不过异步模式虽然性能不错,但特殊情况下会导致数据出现丢失,因此也会存在风险,这时半同步模式就出现了!

半同步复制

半同步模式:当客户端的数据到来时,会先写入到主节点中,接着主节点会向所有从节点发送一个写入数据的请求,但半同步模式中无需等待所有从节点全部写入完成后再返回,而是只要有一个从节点写入成功并返回了ACK,则会直接向客户端返回写入成功,这样既能够保证性能,又能够确保数据不丢失。

同时为了避免网络延迟造成主库长时间收不到从库的ACK,因此在配置半同步式复制时,会有一个rpl_semi_sync_master_timeout参数来控制超时时间,其默认值是10000ms/10s,如若主库在10s内依旧未收到从库的ACK,则会将复制模式切换成异步模式,切成异步模式后,会在后续网络正常后再次切回半同步模式。

主库配置:

gtid_mode=ON
enforce_gtid_consistency
    rpl_semi_sync_master_enabled=ON
    rpl_semi_sync_master_timeout=3000
    rpl_semi_sync_master_wait_point=before_commit
  • gtid_mode=ONenforce_gtid_consistency:开启全局事务ID模式。
  • rpl_semi_sync_master_enabled=ON:启用半同步复制。
  • rpl_semi_sync_master_timeout:等待从服务器确认的时间,单位毫秒。
  • rpl_semi_sync_master_wait_point=before_commit:在提交事务前等待确认。

从库配置:

server-id=2
relay-log=mysql-relay-bin
gtid_mode=ON
enforce_gtid_consistency
rpl_semi_sync_slave_enabled=ON
  • server-id:每个服务器必须有唯一的标识符。
  • relay-log:指定中继日志文件名前缀。

配置从服务器连接到主服务器

CHANGE MASTER TO
    MASTER_HOST='master_host',
    MASTER_USER='repl_user',
    MASTER_PASSWORD='repl_password',
    MASTER_LOG_FILE='mysql-bin.000001',
    MASTER_LOG_POS=107,
    MASTER_AUTO_POSITION = 1;
  • MASTER_HOST:主服务器地址。
  • MASTER_USERMASTER_PASSWORD:用于复制的用户和密码。
  • MASTER_LOG_FILEMASTER_LOG_POS:主服务器上的日志文件和位置。
  • MASTER_AUTO_POSITION = 1:使用GTID自动定位。

但实际上这种只要求一个节点返回ACK的半同步模式,依旧存在数据丢失风险,所以Zookeeper中,是要求收到一半从节点以上的ACK时,也就是一半从节点以上写入数据成功后,才会向客户端返回写入成功,至于为什么是一半写入成功后就返回,具体原因跟其内部的ZAB一致性协议有关,这里就不展开叙述了。

增强式半同步复制/无损复制

增强式半同步复制也被称为无损复制,这是MySQL5.7版本中引入的一种新技术,在MySQL5.7版本中就不存在普通的半同步模式了,当将复制模式配置成半同步时,默认就会选用无损复制模式,和之前传统的半同步复制区别在于:从after-commit变成了after-sync,啥意思呢?

  • after-commit:主库在未收到从库的ACK之前,虽然不会给客户端返回写入成功,但本质上在MySQL中会提交事务,也就是主库中的其他事务是可以看见对应数据的,当此时出现宕机时,就会导致旧主上能查询出的数据,在新主(原本的从库)上无法查询出来了。
  • after-sync:当主库未收到从库的ACK之前,也不会在主库上提交事务,也就是保证了主从节点的数据强一致性,解决了after-commit中存在的问题。

其实简单来说,无损复制中等待ACK的动作会放到事务提交前进行,而传统半同步复制中,等待ACK的动作会放到事务提交后进行。两者之间的区别就在于:对主从节点的数据严格性不同,一般情况下,无损复制会比传统半同步复制开销更大一些,因为事务迟迟不提交,会导致对应的锁资源不会主动释放,其他需要获取对应锁资源的事务只能阻塞等待,这会造成主库的整体性能出现一定影响。

上面聊完了主从复制的四种数据同步方式,接着来聊一聊MySQL5.6中,两种新的复制特性,即从库数据的延迟复制,和从库数据的并行复制,展开说说吧~

延迟复制

延迟复制通常用于一些特殊场景,它可以支持从库数据的延迟同步,也就是当从库上的I/O线程,将主库的Bin-log日志请求回来后,从节点的SQL线程并不会立刻解析日志执行,而是等待一段时间后再解析日志执行,这个等待的时间可以由开发者来配置,一般建议设为3~6小时之间。

那延迟复制的好处在于什么呢?可以防止误删操作,如若在主库上不小心误删了大量数据、表、库或其他数据库对象,因为从库并不是立即执行同步过去的记录,因此可以及时通过从节点上的数据回滚数据。除此之外,也能对一些线上Bug进行实时观测,比如一个无法复现的故障问题发生时,如果发现时还在配置的延迟复制时间内,则可以去到从库上观察。

但开启延迟复制,基本上就无法再对主从架构做读写分离,毕竟很少有业务能够接受3~6小时的数据延迟,因此延迟复制的技术,通常都仅适用于一些作为备库的节点使用。