正常情况下,只要主库执行更新生成的所有binlog,都可以被传到备库并被正确地执行,备库就能达到跟主库一致的状态,这就是最终一致性,而MySQL要提供的高可用能力,只有最终一致性是不够的。
主备延迟
主备切换可能是一个主动运维动作,比如软件升级、主库所在机器按计划下线等,也可能是被动操作,比如主库所在机器掉电。
先看主动切换的场景。首先介绍同步延迟的概念,与数据同步有关的时间点主要包括三个:
-
主库A执行完成一个事务写入binlog,将这个时刻记为T1;
-
之后传给备库B,把备库B接收完这个binlog的时刻记为T2;
-
备库B执行完这个事务,将这个时刻记为T3。
主备延迟指的是,同一个事务主备库执行完成的时间差,即T3-T1。
可以在备库上执行show slave status命令,其返回结果里会显示seconds_behind_master,这个值计算的就是T3-T1。
如果主备库机器的系统时间设置不一致,会不会导致主备延迟的值不准呢?答案是不会的,备库连接到主库的时候,会通过执行SELECT UXIN_TIMESTAMP()函数来获得当前主库的系统时间,如果此时发现两库系统时间不一致,备库执行seconds_behind_master计算时会扣除该差值。
网络正常时,T2-T1是很短的,主备延迟的主要来源是备库接收完binlog和执行完这个事务之间的时间差。所以,主备延迟最直接的表现是,备库消费中转日志(relay log)的速度,比主库生产binlog的速度要慢。
主备延迟的来源
首先,有些部署条件下备库所在机器性能要比主库所在的机器性能差。
有些人部署时想着反正备库没有请求,可以用差一点的机器,但实际上更新过程也会触发大量读操作,当备库主机上的多个备库都在争抢资源时,就可能导致主备延迟。
现在这种部署比较少了,因为主备可能随时切换,所以主备库一般选用相同规格的机器,并且做对称部署。
第二,备库的压力大。
备库一般用来提供一些读能力,如果大量查询,备库上的查询可能耗费大量CPU资源,影响同步速度,造成主备延迟。
这种情况一般的处理方法:
-
一主多从,让多个从库分担读的压力;
-
通过binlog输出到外部系统,比如Hadoop,让外部系统提供统计类查询能力。
第三是大事务。
主库上必须等事务执行完才会写入binlog再传给备库。那么,如果一个主库上的语句执行10分钟,意味着这个事务可能会导致从库延迟10分钟。常见的大事务有一次性用delete删除大量数据、大表DDL等。
第四是备库的并行复制能力,这个下篇文章再介绍。
由于主备延迟的存在,所以在主备切换的时候,就相应的有不同的策略。
可靠性优先策略
上篇文章提到的双M结构:
