mysql 主从复制
mysql主从复制是构建基于Mysql大规模、高性能应用的基础。也是mysql数据备份、读写分离、业务拆分的基石。
同步方式
- 异步:主库把binlog日志发送给从库即返回成功,性能最好,但是可能会造成主从不一致。
- 半同步方式:一主多从模式下,有一个从节点返回成功,即成功,不必等待所有的从库是否成功。
- 全同步:等待所有的从节点返回成功。性能最低。
- 基于GTID
复制基本原理
- master(主库)开启binlog
- slave(从库)开启2个线程:IO线程,SQL线程
大概流程
- 从库的IO线程连接至master。
- 当master中有数据发生修改或者新增时,会顺序写入binlog中并且将相应的数据发送给从库的Io线程。
- 从库IO线程拿到数据之后,会将数据顺序写入relaylog(中继日志)。
- 从库的SQL线程从relaylog顺序读取日志,重放至从库中。
ps: 从库的IO线程与从库的SQL线程是并发执行
主从不一致的几个原因
- 资源不足;比如一般情况下备库性能可能会比主库要差,如果执行某些比较耗时的操作,消耗了大量的CPU资源,就会影响同步的效率。
- 主库如果有大事务在执行;比如执行一个事务数10分钟,那么binlog的写入必须等待事务完成之后才会写入,然后才会发送给从库,那么这个就已经出现了主从不一致,从库延时。
- 从上述流程其实可以看出,主库的写操作是顺序写 binlog, 从库单线程去主库顺序读 binlog,然后。 从库取到 binlog 之后顺序写入中继日志以及的从库的SQL线程也是顺序读中继日志。这些顺序读以及顺序写操作效率都是比较高的。但是在最后一步中:从库的SQL线程重放日志到从库时变成了随机的操作,而不是顺序的,所以此时成本会提高(单线程复制延时的主要原因)。
- 从库在同步数据的同时,可能跟其他查询的线程发生锁抢占的情况,此时也会发生延时,
- 当主库的 TPS 并发非常高的时候, 产生的 DDL 数量超过了一个线程所能承受的范围的时候, 那么也可能带来延迟
- 在进行 binlog 日志传输的时候, 如果网络带宽也不是很好, 那么网络延迟也可能造成数据同步延迟这些就是可能会造成备库延迟的原因
复制的演进过程
- 5.6 之前从库的SQL线程是单线程,也就是复制过程会出现延时(上述第4点)
- 5.6 版本引入了SQL线程为多线程复制。之前的SQL线程变成了coordinator线程(协调线程,用于分发日志给worker线程),然后增加了多个worke线程(执行日志)。但是这里的多线程是基于库的即协调线程是按照库的粒度来分发日志的,实际上很多场景下有可能大部分甚至全部的表都在一个库里,按照这种分发粒度策略,其实并没有什么卵用,还是分配到同一个线程和之前的单线程一样(但是5.6中还是增加了很多有用的功能,为后续的优化垫下了基础:比如GTID,组提交)。
- 5.7 真正的多线程复制(MTS)。
GTID
概述
- global transaction identifieds,全局事务标识;每个事务都有一个与之对应的GTID。
- GTID = server_uuid:seq (server_uuid是数据库服务第一次启动时生成,并持久化到 DATADIR/auto.cnf 文件里,每台机器都不一样,seq每个mysql服务的事务ID,一般自增)。
- slave 端的 binlog 是必须开启,但是从 5.7.5 版本开始无需在 GTID 模式下启用参数 log_slave_updates
流程
- 当Master上有事务提交前,会自动化生成一个GTID,然后写入binlog。
- slave通过IO线程将binlog,同步至slave的relay日志。
- slave的sql线程读取relay日志,获取其中的GTID并与自己的binlog作对比。
- 如果slave的binlog中已经有了GTID则说明已经,执行过了。反之就执行该事务,并且将该GTID记录至binlog中。
相关参考
最后
- 如有不对之处欢迎指正。
本作品采用《CC 协议》,转载必须注明作者和本文链接