勤快学

PhxSQL的Master管理

MySQL多Master同时写入会导致数据的不一致。如图5,机器A是旧Master,在收到机器B成为了新Master的消息之前提交了Transaction 3;而同时机器B已成为新Master,Transaction 3则会留在机器A而未复制到机器B,最终两机的数据不一致。

MySQL多Master问题的产生,源于机器间无法得知当前Master的状态,最后导致两台机器的数据不一致。

即使使用外部服务(例如zookeeper)也无法解根本问题。

对Master查询和查询之后的操作不是原子操作,无法保证操作时的准确状态(例如机器A向外部服务查询得知自己是Master,然后执行复制Binlog操作。但期间出现故障导致两个操作之间停顿了很长时间(譬如1天)。在该期间内Master被切换,使得机器A在执行复制Binlog时,已不再是Master,导致了多Master的情况发生。)

Master管理依赖外部服务的稳定性。

多Master问题由于细节太多,暂不在此讨论。

PhxSQL自身进行了Master管理,具有以下特点:

Master通过Paxos协议投票选出。

Master带有租约,并定时续租。租约过期后,需重新选举新的Master。

全局只有1个Master,或者没有Master存在。

有效拒绝过期Master的非法写入。

PhxSQL的Master自动切换

PhxSQL实现了旧Master的自动数据回滚和Master管理,使得PhxSQL可以安全地实现Master的自动切换,提供高可用服务。和常见的MySQL切换Master方案不同,PhxSQL在切换Master之后仍然保证集群内各机数据一致。

PhxSQL自动Master流程如下:

Slave机器上的Phxbinlogsvr定期检查Master是否过期。如果过期转第2步,否则继续第1步;

Phxbinlogsvr检查本机MySQL是否已执行完所有Binlog。如果已完成转第3步,否则继续第1步;

Phxbinlogsvr发起投票选举新的Master。如果投票成功,提升本机MySQL为Master,关闭readonly开关;否则继续第1步;

旧Master恢复,本机的Phxbinlogsvr查询发现已不是Master,切换MySQL角色为Slave,设置从本机Phxbinlogsvr拉取Binlog,并开启readonly开关。

Phxsqlproxy请求透传

Phxbinlogsvr解决了多Master同时写入的问题,使得MySQLClient向旧Master写入数据会产生失败。虽然保证了数据的一致性,但仍存在下面2个问题:

MySQLClient持续向旧Master写入数据,从而持续的失败。(服务不可用)

部分MySQLClient向新Master写入数据,但其他MySQLClient仍然向旧Master读取数据,导致读不到最新的数据。

上述两个问题都是由于MySQLClient的Master信息更新不及时;部分Client没有及时更新,使得有可能产生PhantomRead(两次读的结果不一致)。

若Slave机器被访问,Phxsqlproxy则会把请求透传到Master机器的Phxsqlproxy。由于PhxSQL Master的全局唯一性,保证了只存在一台MySQL被访问。从而解决了多台机器同时被读写的问题。