原理:
Mysql的主从复制中主要有三个线程(Master一条线程和Slave中的两条线程):
- master(binlog dump thread)
- slave(I/O thread 、SQL thread)
master(binlog dump thread)主要负责Master库中有数据更新的时候,会按照binlog格式,将更新的事件类型写入到主库的binlog文件中,并且,Master会创建log dump线程通知Slave主库中存在数据更新,这就是为什么主库的binlog日志一定要开启的原因。
-
I/O thread线程在Slave中创建,该线程用于请求Master,Master会返回binlog的名称以及当前数据更新的位置、binlog文件位置的副本,然后,将binlog保存在 「relay log(中继日志)」 中,中继日志也是记录数据更新的信息。
SQL线程也是在Slave中创建的,当Slave检测到中继日志有更新,就会将更新的内容同步到Slave数据库中,这样就保证了主从的数据的同步。
以上就是主从复制的过程,当然,主从复制的过程有不同的策略方式进行数据的同步,主要包含以下几种:
- 「同步策略」:Master会等待所有的Slave都回应后才会提交,这个主从的同步的性能会严重的影响。
- 「半同步策略」:Master至少会等待一个Slave回应后提交。
- 「异步策略」:Master不用等待Slave回应就可以提交。
- 「延迟策略」:Slave要落后于Master指定的时间。
对于不同的业务需求,有不同的策略方案,但是一般都会采用最终一致性,不会要求强一致性,毕竟强一致性会严重影响性能。
异步复制:
主库执行完操作后,写入binlog日志后,就返回客户端,这一动作就结束了,并不会验证从库有没有收到,完不完整,所以这样可能会造成数据的不一致。
说到底,复制过程中数据是否一致,主要取决于Binlog日志的安全性与完整性
在MySQL中,有sync_binlog=n这一参数,他的值表示每进行n次事务提交,MySQL就将Binlog刷新到磁盘。如果这个值为1,就代表每提交一次事务(SQL),就将Binlog往磁盘刷新一次,这样一来,就算数据库宕机了,那么最多只能损失一次事务的数据。
但是,一旦多个事务并发提交时,由于受sync_binlog的限制,MySQL只能按顺序来处理这些请求,另外,高频率的刷新binlog对IO的影响也很大,进一步影响了数据库的性能,所以,一般这个值都设为0或者其他值,在数据的安全性和高并发下的性能之间取得一个平衡。
sync_binlog:
这个参数是对于MySQL系统来说是至关重要的,他不仅影响到Binlog对MySQL所带来的性能损耗,而且还影响到MySQL中数据的完整性。对于“sync_binlog”参数的各种设置的说明如下:
sync_binlog=0,当事务提交之后,MySQL不做fsync之类的磁盘同步指令刷新binlog_cache中的信息到磁盘,而让Filesystem自行决定什么时候来做同步,或者cache满了之后才同步到磁盘。
sync_binlog=n,当每进行n次事务提交之后,MySQL将进行一次fsync之类的磁盘同步指令来将binlog_cache中的数据强制写入磁盘。
在MySQL中系统默认的设置是sync_binlog=0,也就是不做任何强制性的磁盘刷新指令,这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。而当设置为“1”的时候,是最安全但是性能损耗最大的设置。因为当设置为1的时候,即使系统Crash,也最多丢失binlog_cache中未完成的一个事务,对实际数据没有任何实质性影响。
从以往经验和相关测试来看,对于高并发事务的系统来说,“sync_binlog”设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多。
show variables like 'sync_binlog';
set global sync_binlog=0;
为了更加有效的保护Binlog的安全性和完整性,MySQL5 .5之后引入了半同步复制。
半同步复制
半同步复制,当主库每提交一个事务后,不会立即返回,而是等待其中一个从库接收到Binlog并成功写入Relay-log中才返回客户端,所以这样就保证了一个事务至少有两份日志,一份保存在主库的Binlog,另一份保存在其中一个从库的Relay-log中,从而保证了数据的安全性和一致性。
另外,在半同步复制时,如果主库的一个事务提交成功了,在推送到从库的过程当中,从库宕机了或网络故障,导致从库并没有接收到这个事务的Binlog,此时主库会等待一段时间(这个时间由rpl_semi_sync_master_timeout的毫秒数决定),如果这个时间过后还无法推送到从库,那MySQL会自动从半同步复制切换为异步复制,当从库恢复正常连接到主库后,主库又会自动切换回半同步复制。
半同步复制的“半”体现在,虽然主从库的Binlog是同步的,但主库不会等待从库执行完Relay-log后才返回,而是确认从库接收到Binlog,达到主从Binlog同步的目的后就返回了,所以从库的数据对于主库来说还是有延时的,这个延时就是从库执行Relay-log的时间。所以只能称为半同步。