引言:
复制模式概述:
半同步模式:主库收到commit 后,依次执行 redo log prepare,写binlog/发往备库(两个步骤并行),等待备库回复收到ack,redo log commit,给用户回复成功。这个有一个等待ack的超时,当超过设置的时长,那么自动降级为异步模式;当网络或备库恢复后,备库IO线程开始追赶主库,当追上后,复制模式会自动升级为半同步模式。
强同步模式:主库收到commit 后,依次执行 redo log prepare,写binlog/发往备库(并行),等待备库fsync到磁盘后,redo log commit ,给用户恢复成功。
保证可靠性:
异步模式下,由于主库写入事务时,不会传递到备库(无论物理复制还是逻辑复制),那么当主库down机时,备库数据和主库是很可能不一致的,所以此时是无法保证可靠性的。对于我们阿里云用户使用的mysql库,在此模式下就没任何办法了么?其实不是,在此模式下,我们提供了以下的措施来最大限度的保证主备一致性:
1)备库一定是在应用完所有传递到备库的日志后,才开放可写。这样就最大限度保证备库的数据线是一致的,不会导致双写的问题(一边应用日志,一边接受写入)。
2)主库增加时间戳,通过复制关系同步到备库,当主库故障时,HA系统(数据库高可用系统)通过比对最后一次成功写入主库的时间戳及备库上从主库接受到日志后应用掉后的时间戳进行比较,当大于某个阀值时,不做链路切换动作。这样能够保证主备间数据不一致的时间长度在可控范围内。
3)判断主库故障的条件更加苛刻,当不是主库所在主机是不可恢复的故障时,优先使用主库重启的方式来解决,确保数据线的一致性。
半同步模式下,当网络与主备库都正常情况下,主备库的数据一定是最终一致的(备库需要应用relay日志),当主库故障时,要么事务在主库还没有应用,没有传递日志到备库;要么事务在主库应用了,日志也传递到了备库。所以最终是一致的。
那么是不是半同步下,数据就不丢了呢?我们前面说过,当网络,和备库出现间歇性问题时,那么半同步会降级为异步,那么如果恰恰在此时,备库的IO线程正在追赶主库的binlog位点,但是还没有完全同步上,主库down了(也就是说此时出现延迟的情况下),主备数据就会出现不一致。
针对这个问题,我们研发了double binlog复制模式,该模式是在半同步基础上更进一步,在主备库间除了半同步复制通路,同时还有一个异步复制通路,平时在主备库及网络都健康情况下,由半同步通路持续的保持复制关系,确保主备数据一致;但是当在备库或主备间网络出现问题,一旦备库或网络恢复后,备库不再使用单一的链路来复制binlog,会同时开启两条复制链路,一条继续从上次备库最后一次接到的位点来复制,一条从主库写入的最新一条事务日志来复制,那么落后的复制不必追赶到最新的主库binlog位置才升级为半同步,而是追赶到备库恢复后的位点即可。这时两条复制通路的binlog就可以完整接上,然后等待备库继续掉日志后,主备数据就完全同步了。
总结:
所以通过这个特性,我们能做到在主备出现延迟后,依然能够保证主备的一致性。目前金融专有云已经开始使用该复制模式,对数据要求性高的朋友依然可以使用mysql一主一备的低成本方式来满足企业的日常需求。