Master-Master 主从切换

同步延时

  1. 主库A执行完成一个事务,写入binlog,记为T1
  2. 然后传给从库B,从库B接收该binlog,记为T2
  3. 从库B执行完成这个事务,记为T3
  4. 同步延时:T3-T1
    • 同一个事务,在从库执行完成的时间主库执行完成的时间之间的差值
    • SHOW SLAVE STATUS中的Seconds_Behind_Master

Seconds_Behind_Master

  1. 计算方法
    • 每个事务的binlog里面都有一个时间字段,用于记录该binlog主库上的写入时间
    • 从库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间点差值,得到Seconds_Behind_Master
    • T3-T1
  2. 如果主库与从库的时间不一致,Seconds_Behind_Master会不会有误差?
    • 一般不会
    • 从库连接到主库时,会通过SELECT UNIX_TIMESTAMP()获取当前主库的系统时间
    • 如果从库发现当前主库的系统时间与自己的不一致,在计算Seconds_Behind_Master自动扣除这部分差值
    • 但建立连接后,主库或从库又修改了系统时间,依然会不准确
  3. 网络正常的情况下,T2-T1通常会非常小,此时同步延时的主要来源是**T3-T2**
    • 从库消费relaylog的速度跟不上主库生成binlog的速度

延时来源

  1. 从库所在机器的性能要弱于主库所在的机器
    • 更新请求对于IPOS的压力,在主库从库上是无差别
  2. 非对称部署:20个主库放在4个机器上,但所有从库放在一个机器上
    • 主从之间可能会随时切换,现在一般都会采用相同规格的机器+对称部署
  3. 从库压力大
    • 常见场景:管理后台的查询语句
    • 从库上的查询耗费大量的CPU资源IO资源,影响了同步速度,造成了同步延时
    • 解决方案
      • 一主多从,分担读压力,一般都会采用
      • 通过binlog输出到外部系统,例如Hadoop
  4. 大事务
    • 主库上必须等待事务执行完成后才会写入binlog,再传给从库
    • 常见场景1:一次性删除太多数据(如归档的历史数据)
      • 解决方案:控制每个事务删除的数据量,分多次删除
    • 常见场景2:大表DDL
      • 解决方案:gh-ost
  5. 从库的并行复制能力(后续展开)

切换策略

可靠性优先

切换过程一般由专门的HA系统完成,存在不可用时间(主库A和从库B都处于只读状态)

  1. 判断从库BSeconds_Behind_Master值,当小于某个值(例如5)才继续下一步
  2. 主库A改为只读状态(readonly=true
  3. 等待从库BSeconds_Behind_Master值降为0
  4. 从库B改为可读写状态(readonly=false
  5. 业务请求切换至从库B

可用性优先

不等主从同步完成,直接把业务请求切换至从库B,并且让从库B可读写,这样几乎不存在不可用时间,但可能会数据不一致

表初始化

1
2
3
4
5
6
7
CREATE TABLE `t` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`c` INT(11) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO t (c) VALUES (1),(2),(3);

插入数据

1
2
3
INSERT INTO t (c) VALUES (4);
-- 主库上的其它表有大量的更新,导致同步延时为5S,插入c=4后发起了主从切换
INSERT INTO t (c) VALUES (5);

MIXED

  1. 主库A执行完INSERT c=4,得到(4,4),然后开始执行主从切换
  2. 主从之间有5S的同步延迟,从库B会先执行INSERT c=5,得到(4,5),并且会把这个binlog发给主库A
  3. 从库B执行主库A传过来的INSERT c=4,得到(5,4)
  4. 主库A执行从库B传过来的INSERT c=5,得到(5,5)
  5. 此时主库A和从库B会有两行不一致的数据

ROW

  1. 采用ROW格式的binlog时,会记录新插入行的所有字段的值,所以最后只会有一行数据不一致
  2. 主库A和从库B的同步线程都会报错并停止duplicate key error

小结

  1. 使用ROW格式的binlog,数据不一致的问题更容易发现,采用MIXEDSTATEMENT格式的binlog,数据可能悄悄地不一致
  2. 主从切换采用可用性优先策略,可能会导致数据不一致,大多数情况下,优先选择可靠性优先策略
  3. 在满足数据可靠性的前提下,MySQL的可用性依赖于同步延时的大小(同步延时越小可用性越高

参考资料

《MySQL实战45讲》