mysql 5.5、5.6、5.7的主从复制改进

问题


mysql一直以来的主从复制都是被诟病的理由之一,原因是:

1、最主要的主从复制速度问题

mysql采取的是主执行提交之后,将语句记录进binlog,从启动一个IO线程从主传输binlog到本地,进入本地的relaylog;从另外启动一个SQL线程负责顺序执行relaylog中的语句,对修改在从机上重做,即是一个异步的拷贝

导致的问题是从机数据大部分情况下会延后。主机对本地磁盘的IO,从机从主机传输的网络IO,从机本地的磁盘IO,最后从机数据的IO,经过了四个过程,即使服务器和网络配置都很快,理论上也一定是有延迟的;如果服务器和网络配置有瓶颈,这个延迟就会扩大化到影响业务的程度,最直接的就是读写分离的情况下,导致前端写入操作明明已经回报完成了,后端读数据时却显示没有完成

2、主宕机的切换后脏数据问题

mysql的主从目的之一,就是在主宕机的情况下,能及时切换到备机继续提供服务,不至于整个系统挂掉。但就是因为主从复制要经过复制这一消耗IO的步骤,主在挂掉的一瞬间,一般主从都会有一定量的数据区别,出现在主执行完的但还未传输到从上的部分,这部分就是所谓的脏数据,即之前明明已经有了的数据,又没有了。

这样的脏数据,同样会导致前后不一致,如果服务器和网络配置不高,本来同步复制就慢的情况下,会导致极大的差别




oracle公司收购了sun,对mysql进行升级换代之后,有了巨大的改进,在5.5、5.6、5.7版本都针对主从有升级改造,在目前的5.7版本达到了非常高的可用性,配合最新的HA中间件mysql fabric,可以达到以前的几倍的稳定性

下面来详细讲一讲这三个版本中,oracle都对主从具体做了什么改进


一、5.5版本

添加了一个semi-sync replication(半同步复制)的插件,这个插件就是为了优化同步复制的脏数据问题存在的

原理是在传输binlog时,要求从机返回ack证明自己拿到了数据,在至少一个从机返回ack后,主机才将数据修改提交到本地,这样能保证至少一个从机和主机是完全一致的。

举例说明:

正在主机上持续不断插入数据时,始终有一部分数据处在传输到从机的过程中,这部分数据在主机上已经是执行成功的状态,但因为还没传输并完成收到任何一台从机的回应,所以尚未持久化。这个瞬间主机宕机了,数据传输不完,从机的回应也收不到了,主机重启后,主机上的这部分数据因为没有收到回应进行持久化,所以消失了。而从机上的这部分数据因为尚未接收完全,也不能作为一个relaylog提交执行,所以从机也没有这部分数据。最终的结果就是,这部分脏数据就被丢弃了,不会造成主从的不一致。


优点

保证至少一个从机和主机在任何时候都是一致的,不会出现你比我多或者我比你多的情况,不需要进行主从恢复后的数据恢复行为。在只有一主一从的情况下,整个系统永远不会有脏数据


缺点

显而易见的,一主多从的情况下,除了一台从外,其他从都会有数据不一致现象。另外,没有成功传输的数据就被直接丢弃了,找都找不回来,如果涉及金融交易,瞬时的数据丢失也是不可原谅的,所以这种架构在数据重要度非常高的业务里不能用


二、5.6版本

5.6版本对主从同步进行了改进,加入了GTID的事务区分标志,又加入了多线程复制和组提交的新模式


GTID,全局事务ID
此处转载自:http://www.cnblogs.com/cenalulu/p/4309009.html

GTID是事务提交时创建分配的唯一标识符,所有事务均与GTID一一映射。
GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。下面是一个GTID的具体形式
5882bfb0-c936-11e4-a843-000c292dc103:1
这个字符串,用“:”分开,前面表示这个MySQL实例的server_uuid,这是一个128位的随机字符串,在第一次启动时生成(函数generate_server_uuid),对应的variables是只读变量server_uuid。 它能以极高的概率保证全局唯一性,并存到文件

那么GTID功能的目的是什么呢?具体归纳主要有以下两点:

  • 根据GTID可以知道事务最初是在哪个实例上提交的
  • GTID的存在方便了Replication的Failover

这里详细解释下第二点。我们可以看下在MySQL 5.6的GTID出现以前replication failover的操作过程。假设我们有一个如下图的环境

此时,Server A的服务器宕机,需要将业务切换到Server B上。同时,我们又需要将Server C的复制源改成Server B。复制源修改的命令语法很简单即CHANGE MASTER TO MASTER_HOST='xxx', MASTER_LOG_FILE='xxx', MASTER_LOG_POS=nnnn。而难点在于,由于同一个事务在每台机器上所在的binlog名字和位置都不一样,那么怎么找到Server C当前同步停止点,对应Server Bmaster_log_filemaster_log_pos是什么的时候就成为了难题。这也就是为什么M-S复制集群需要使用MMM,MHA这样的额外管理工具的一个重要原因。
这个问题在5.6的GTID出现后,就显得非常的简单。由于同一事务的GTID在所有节点上的值一致,那么根据Server C当前停止点的GTID就能唯一定位到Server B上的GTID。甚至由于MASTER_AUTO_POSITION功能的出现,我们都不需要知道GTID的具体值,直接使用CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION命令就可以直接完成failover的工作。 So easy不是么?


多线程并发复制

针对多库的情况,开启多线程,每个库一个独立IO线程,可以交叉并发传输。在不同库同一时间进行的操作理论上是互不影响的,可以同步进行,你改你的,我改我的。极大改善了多库业务的复制速度。但是缺点也是显而易见的,如果业务始终只有一个库,或者数据库压力都集中在一个库上,其他库基本没什么操作,这样的两种情况下,针对库的多线程基本没有意义,还是和以前的单线程复制是一样的速度


组提交

这个是极大提升了binlog和innodb的redolog的落盘(保存到磁盘)效率。组提交的原理是:

多个事务同时执行完成,数据需要持久化到log中时,会全部进入一个待提交队列。最先进入队列的事务线程成为leader线程,其他后续进入的成为follower线程,leader线程将会获得这个队列的控制权,就是会获得一个锁,全权负责本次队列中所有事务的落盘操作。接着联系其他follower线程,将他们的提交内容获取得到,并让他们等待自己完成操作。接着这个leader线程会进入后续的落盘过程,等完成后,会通知本队列中所有follower线程落盘已经完成,可以返回成功状态了。

好处是多次磁盘IO可以合并成一次磁盘IO,减少读写次数,有效提高了写日志的速度。也就意味着在主从同步过程中,磁盘IO这一块的效率提高了


三、5.7版本

5.7是mysql主从复制上一个划时代的版本,原因是mysql将日志组提交的模式应用到了主从网络IO上,在原来已经通过组提交优化了的磁盘IO效率基础上,对网络IO效率进行了同样的优化,正是将困扰mysql主从复制多年的两大难题解决的最重要版本。解决方案,官方称之为Enhanced Multi-Threaded Slave(简称MTS)


Enhanced Multi-Threaded Slave(简称MTS)

增强的多线程备份。即通过从机开启多个IO线程,主机通过组提交的模式并行地传输事务进行复制,具体思想简单易懂,一言以蔽之:一个组提交的事务都是可以并行回放,因为这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交)

但是网络IO是有先后顺序的,和传输顺序通常是不同的,收到事务后需要区分先后顺序来执行,否则从机执行顺序和主机不同,数据同样会出错。获取事务先后顺序的方法也很简单,就是使用的MYSQL 5.6已经加入的GTID,因为每个事务在提交时已经按顺序生成了唯一的GTID,从机读到事务后按照GTID的顺序执行就可以了

在这样的模式下,从机可以同时消费主机的多个事务队列,在同一时间接收到更多的数据传输,有效降低了数据来不及传输而导致的宕机数据丢失的概率


总结


mysql 5.7版本已经是mysql主从复制方面一个集大成的版本,非常有必要升级到这个版本,以提高生产环境主从稳定性和数据完整性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值