MySQL - 主从复制的几种方式

用户头像
Aaron_涛
关注
发布于: 2020 年 07 月 21 日
MySQL - 主从复制的几种方式

1. 什么是主从复制

主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库。

可以理解为,主数据库的数据的任何变化,从数据库都会跟着发生变化。

2. 主从复制的作用

  1. 在从服务器可以执行查询工作,降低主服务器压力;(主库写,从库读,降压)读写分离

  2. 在从主服务器进行备份,避免备份期间影响主服务器服务;容灾

  3. 当主服务器出现问题时,可以切换到从服务器。提高可用性



3. 主从复制的基本原理





步骤含义:

  1. SQL语句操作变化存入BinLog日志中

  2. slave上线,连接到master服务器,进行数据同步

  3. dump thread线程把Binlog数据发送到slave中

  4. slave启动之后,创建一个I/O线程,读取master传过来的Binlog内容并写入到Relay log.

  5. slave还会创建一个SQL线程,从Relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db.



3.1. 并行加速复制

传统的MySQL(5.6 版本之前)主从复制是单线程复制,即:1个dump thread线程,1个IO线程,1个SQL线程

想要提高复制的效率,很自然考虑多线程,虽然有3种线程可以扩展为多线程。但是MySQL只将SQL线程扩展为多线程

为什么Dump和IO线程不能多线程?

  1. dump线程和IO线程都是负责网络传输,如果将这里扩展为多线程那么会将一份Binlog日志分割为多份,并行传输,那么在slave端将会要额外的增加代码考虑如何将多份日志还原为原来的Binlog,大大增加难度。

  2. 性能瓶颈不在IO,扩展后也没有多大效率提升。

画外音:为什么Redis 6.0使用IO多线程增强性能,MySQL这里使用IO多线程却不行?

Redis是多个Client节点一个Server节点(暂且这么看),IO线程需要处理多个不同Client来源的请求;MySQL主从复制,本质上是1个Client端一个Server端,增大IO线程也无济于事。



SQL线程并行后的难点

相同两个事务的执行顺序。假设A,B两个事务,A先执行,B后执行,都同时改同一行数据,如果主从同步过程中,因为并行执行,B先执行,A后执行,那么将导致数据不一致问题。所以需要一个机制去防止此类事情的发生。

对于这个问题,MySQL会判断当前需要复制的事务Id和与之前复制完毕的事务id进行比对,判断是否处于当前执行完毕事务之后,否则只能等待前驱事务复制完毕。(大概原理,本文不是讲解并行复制,不深入讲解



4. MySQL主从复制的方式

4.1. 异步复制



MySQL 默认的复制策略,Master处理事务过程中,将其写入Binlog就会通知Dump thread线程处理,然后完成事务的提交,不会关心是否成功发送到任意一个slave中



问题:一旦Master 崩溃,发送主从切换将会发送数据不一致性的风险。

画外音:性能最好

4.2. 半同步复制



Master处理事务过程中,提交完事务后,必须等至少一个Slave将收到的binlog写入relay log返回ack才能继续执行处理用户的事务。

配置

rpl_semi_sync_master_wait_point = AFTER_COMMIT (什么时间点开始等ack)【这里MySQL 5.5并没有这个配置,MySQL5.7 为了解决半同步的问题而设置的,下文有讲解

rpl_semi_sync_master_wait_for_slave_count = 1 (最低必须收到多少个slave的ack)

rpl_semi_sync_master_timeout = 100(等待ack的超时时间)



问题:

  1. 一旦Ack超时,将退化为异步复制模式,那么异步复制的问题也将发送

  2. 性能下降,增多至少一个RTT时间

  3. 数据不一致性问题,因为等待ACK的点是Commit之后,此时Master已经完成数据变更,用户已经可以看到最新数据,当Binlog还未同步到Slave时,发生主从切换,那么此时从库是没有这个最新数据的,用户又看到老数据。

4.3. 增强半同步复制





增强半同步和半同步不同是,等待ACK时间不同

rpl_semi_sync_master_wait_point = AFTER_SYNC唯一区别

半同步的问题是因为等待ACK的点是Commit之后,此时Master已经完成数据变更,用户已经可以看到最新数据,当Binlog还未同步到Slave时,发生主从切换,那么此时从库是没有这个最新数据的,用户又看到老数据。

增强半同步将等待ACK的点放在提交Commit之前,此时数据还未被提交,外界看不到数据变更,此时如果发送主从切换,新库依然还是老数据,不存在数据不一致的问题。



问题:

  1. 一旦Ack超时,将退化为异步复制模式,那么异步复制的问题也将发送

  2. 性能下降,增多至少一个RTT时间

  3. 如果超时时间设置很大,然后因为网络原来长时间收不到ACK,用户提交是被挂起的,可用性收到打击(半同步一样存在)



画外音:感觉MySQL因为直接提供增强半同步,半同步类似个过度产品

4.4. 组复制

MySQL Group Replication(MGR)



MySQL在引擎层完成Prepare操作写Redo日志之后,会被MySQL的预设Hook拦截进入MGR层

MGR层将事务信息打包通过Paxos协议发送到全部节点上,只要集群中过半节点回复ACK,那么将告诉所有节点数据包同步成功,然后每个节点开始自己认证(certify)通过就开始写Binlog,提交事务或者写relay log,数据同步,如果认证不通过则rollback



什么是Certify?

在不同服务器上并发执行的事务之间可能存在冲突。这种冲突是通过检查和比较两个不同的并发事务的写入集来检测的,这个过程称为认证

在认证期间,冲突检测是在行级别执行的:如果在不同服务器上执行的两个并发事务更新了同一行,则存在冲突。

冲突解决过程指出,首先排序的事务将在所有服务器上提交,而第二次排序的事务将中止,因此将在原始服务器上回滚并被组中的其他服务器丢弃。



总结:MGR内部实现了分布式数据一致性协议,paxos通过其来保证数据一致性。



问题

  1. 性能不高

  2. TP999升高,吞吐量降低;增大20%~30%响应时间



5. 对比

我们考虑架构的时候,不应该过于关心它能干啥,应该考虑每一种方式它不能干啥





发布于: 2020 年 07 月 21 日 阅读数: 125
用户头像

Aaron_涛

关注

还未添加个人签名 2018.07.17 加入

互联网搬砖工,热衷分享,喜欢新事物 目前从事营销域技术研发

评论

发布
暂无评论
MySQL - 主从复制的几种方式