MGR基于Paxos协议,多个节点之间强同步的高可用方案,但多个节点的强一致性是保证了最终一致性,在平常的各节点复制中还是异步的。
MGR中有两种需要一致性读的地方
手工或自动发生切换的时候
当主库发生故障时MGR会选举一个新的主节点,新主节点接管后默认是不等待事务补偿到和原主节点相差的这部分数据,就对外提供服务,这时客户端再次发送新的请求时,就有可能与前一次查询到的结果不一致(MySQL 8.0.14之前都采用的是这种方式)数据复制
由于各节点之间复制是异步的,所以会存在两个客户端分别读取不同节点上的数据库时得到的结果不同。
我们很容易想到改成同步的不就好了吗?,但改为同步方式也有两种情况:
- 同步写
每一次写操作都会等待数据同步到各个节点,等待各个节点上都commit(applied)成功。
这种方式适用于以下场景:
- 需要读的强一致性
- 读多写少
- 同步读
这种方式不会等待每个节点都commit(applied)成功,而是每次读操作时会等待数据应用完成,以便读取到的数据是最新的
这种方式适用于以下场景:
- 需要强一致性读
- 写多读少
MGR中的一致性读参数group_replication_consistency
在MySQL8.0.14中增加的group_replication_consistency参数,用来设置一致性读的级别,参数可设置为以下几个值:
- EVENTUAL(默认值):
8.0.14之前的方式,所有的读写操作不会等待数据在各个节点commit(applied)完成
- BEFORE_ON_PRIMARY_FAILOVER
发生切换之后将等待积压的事务应用完成之后,才允许读写操作 - BEFORE
RW事务操作等待之前所有的事务操作全部完成,同时RO事务操作等待之前的事务全部应用完成,保证读的数据是最新正确的。对应我们上面所说的同步读。 - AFTER
RW事务操作会等待其对数据的变更,在所有节点上全部commit(applied)完成,保证之后读的数据是最新正确的。对应我们上面所说的同步写。 - BEFORE_AND_AFTER
BEFORE与AFTER的组合
BEFORE与AFTER的区别之处:
- BEFORE不会等待数据的变更在所有节点上全部commit(applied)完成,可以理解为写操作还是异步的,对于写多读少的场景,这样可以较少同步RW事务的开销
- AFTER写操作在各个节点上是同步的,对于读多写少的场景,可以较少RO事务同步等待的开销。
group_replication_consistency的作用域
此参数在单个节点上可设置为session或者是global,可以根据不同的情况设置session级别,部分数据的同步,这点非常灵活。但是需要注意AFTER与BEFORE_AND_AFTER会影响到集群中的所有节点。同时AFTER与BEFORE_AND_AFTER会影响到所有online的成员,举个例子如下:
1 | # Group with 3 members: M1, M2 and M3 |
即使T2一致性级别为EVENTUAL,如果它在T1已经处于M2的提交阶段时开始执行,则T2等待T1完成提交,然后才能执行
等待时间由什么控制
如果集群压力非常大或者出现什么异常情况则可能会一直等待下去,那么就要有个超时时间,这个超时时间由参数wait_timeout控制(默认是8个小时),如果超过这么长时间则会抛出ER_GR_HOLD_WAIT_TIMEOUT异常
参考资料
https://mysqlhighavailability.com/group-replication-consistency-levels/
https://mysqlhighavailability.com/group-replication-consistent-reads/