微信开源PhxSQL:高可用、强一致的MySQL集群
xiao113
8年前
<p>PhxSQL是一个兼容MySQL、服务高可用、数据强一致的关系型数据库集群。PhxSQL以单Master多Slave方式部署,在集群内超过一半机器存活的情况下,可自身实现自动Master切换,且保证数据一致性。</p> <p>PhxSQL基于Percona 5.6开发。Percona是MySQL的一个分支,功能和实现与MySQL基本一致。因此本文后续直接把MySQL作为讨论对象。</p> <p>MySQL半同步复制存在缺陷,在Master进行切换的场景下,数据难以保证一致。</p> <p>当旧Master复制失败时,旧Master和Updated Slave(已收到Binlog的Slave)需要回滚数据。</p> <p>当Master进行切换时,旧Master仍有部分Client进行读写。</p> <p>关于MySQL半同步复制的数据一致性问题可查看微信后台团队公众号文章MySQL半同步复制的数据一致性探讨。</p> <p>PhxSQL的设计是为了解决MySQL半同步复制的不足,使MySQL集群在Master切换过程中保证数据的一致。</p> <p>PhxSQL架构</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/c0c1950f782b7b9d1b1d19a753745a73.jpg"></p> <p style="text-align: center;">图1 PhxSQL 三层架构</p> <p>为了解决MySQL的两个问题(Binlog复制和Master切换),PhxSQL设计了两个模块(Phxbinlogsvr、Phxsqlproxy)和一个MySQL插件(Phxsync)。Phxbinlogsvr负责处理MySQL的Binlog复制和Master管理;Phxsqlproxy负责透传Client请求到Master;Phxsync插件负责MySQL和Phxbinlogsvr的交互。 一台部署了Phxsqlproxy,MySQL和Phxbinlogsvr的机器称为PhxSQL Node。如图1。</p> <p>PhxSQL复制流程</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/88e0d8ccd54ef1747b24605de1a7de83.jpg"></p> <p style="text-align: center;">图2.1 MySQL复制流程</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/59b18938efe822f65710a2191a286a5d.jpg"></p> <p style="text-align: center;">图2.2 PhxSQL复制流程</p> <p>图2 MySQL和PhxSQL的数据复制流程</p> <p>在PhxSQL中,Phxbinlogsvr负责管理MySQL的角色和存储MySQL的Binlog,Phxbinlogsvr和其管理的MySQL部署在同一台物理机上。</p> <p>MySQL Master在Send Event阶段不再把Binlog复制给Slave,而是通过Phxsync插件,把数据复制到Phxbinlogsvr集群。</p> <p>MySQL Slave也不再从Master获取Binlog,而是从本机的Phxbinlogsvr获取。</p> <p>Phxbinlogsvr集群使用Paxos协议进行数据复制。</p> <p>PhxSQL使用PhxPaxos库,详情请查看微信后台团队公众号文章微信自研生产级paxos类库PhxPaxos实现原理介绍。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/a5e985966adb2c29698b80c58df28e6b.jpg"></p> <p style="text-align: center;">图3 Phxbinlogsvr形成一个可靠日志存储</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/6a90baae40854f638c0afb7340f609a6.jpg"></p> <p style="text-align: center;">图4 重启向Phxbinlogsvr询问PendingBinlog状态</p> <p>从逻辑上来看,利用Paxos协议进行复制,使Phxbinlogsvr形成一个可靠的日志存储。PhxSQL可以看成是为MySQL增加了一个用Paxos实现的可靠Binlog存储,只要集群中多数派机器存活,就可以解决半同步复制的回滚问题。如图3。</p> <p>分别从Master和Slave的角度来解释:</p> <p>Master重启时,通过询问Phxbinlogsvr(多数派)Pending Binlog是否存在来决定是否需要回滚。如图4。</p> <p>Slave从本机Phxbinlogsvr能拉取到的Binlog都已经经过Paxos协议成功复制到多数派机器,因此对于Slave来说不存在回滚的问题。</p> <p>Phxbinlogsvr通过Paxos协议复制数据,很好的解决了MySQL中需要手动回滚Binlog和在大集群时同时需要回滚Updated Slave上的Binlog的问题。</p> <p>PhxSQL的Master管理</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/0b0138251cbba4393a725d126f370a6b.jpg"></p> <p style="text-align: center;">图5 多个Master同时写入数据,导致数据不一致</p> <p>MySQL多Master同时写入会导致数据的不一致。如图5,机器A是旧Master,在收到机器B成为了新Master的消息之前提交了Transaction 3;而同时机器B已成为新Master,Transaction 3则会留在机器A而未复制到机器B,最终两机的数据不一致。</p> <p>MySQL多Master问题的产生,源于机器间无法得知当前Master的状态,最后导致两台机器的数据不一致。</p> <p>即使使用外部服务(例如zookeeper)也无法解根本问题。</p> <p>对Master查询和查询之后的操作不是原子操作,无法保证操作时的准确状态(例如机器A向外部服务查询得知自己是Master,然后执行复制Binlog操作。但期间出现故障导致两个操作之间停顿了很长时间(譬如1天)。在该期间内Master被切换,使得机器A在执行复制Binlog时,已不再是Master,导致了多Master的情况发生。)</p> <p>Master管理依赖外部服务的稳定性。</p> <p>多Master问题由于细节太多,暂不在此讨论。</p> <p>PhxSQL自身进行了Master管理,具有以下特点:</p> <p>Master通过Paxos协议投票选出。</p> <p>Master带有租约,并定时续租。租约过期后,需重新选举新的Master。</p> <p>全局只有1个Master,或者没有Master存在。</p> <p>有效拒绝过期Master的非法写入。</p> <p>PhxSQL的Master自动切换</p> <p>PhxSQL实现了旧Master的自动数据回滚和Master管理,使得PhxSQL可以安全地实现Master的自动切换,提供高可用服务。和常见的MySQL切换Master方案不同,PhxSQL在切换Master之后仍然保证集群内各机数据一致。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/3979ba30dd815ec133b0a554d9b7d3bc.jpg"></p> <p style="text-align: center;">图6</p> <p>PhxSQL自动Master流程如下:</p> <p>Slave机器上的Phxbinlogsvr定期检查Master是否过期。如果过期转第2步,否则继续第1步;</p> <p>Phxbinlogsvr检查本机MySQL是否已执行完所有Binlog。如果已完成转第3步,否则继续第1步;</p> <p>Phxbinlogsvr发起投票选举新的Master。如果投票成功,提升本机MySQL为Master,关闭readonly开关;否则继续第1步;</p> <p>旧Master恢复,本机的Phxbinlogsvr查询发现已不是Master,切换MySQL角色为Slave,设置从本机Phxbinlogsvr拉取Binlog,并开启readonly开关。</p> <p>Phxsqlproxy请求透传</p> <p>Phxbinlogsvr解决了多Master同时写入的问题,使得MySQLClient向旧Master写入数据会产生失败。虽然保证了数据的一致性,但仍存在下面2个问题:</p> <p>MySQLClient持续向旧Master写入数据,从而持续的失败。(服务不可用)</p> <p>部分MySQLClient向新Master写入数据,但其他MySQLClient仍然向旧Master读取数据,导致读不到最新的数据。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/2e900fe110118a01c9c9c11d40537cd9.jpg"></p> <p style="text-align: center;">图7</p> <p>上述两个问题都是由于MySQLClient的Master信息更新不及时;部分Client没有及时更新,使得有可能产生PhantomRead(两次读的结果不一致)。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/f3d746e6f707cffff011f2d8151bbe56.jpg"></p> <p style="text-align: center;">图8 Phxsqlproxy的请求透传</p> <p>若Slave机器被访问,Phxsqlproxy则会把请求透传到Master机器的Phxsqlproxy。由于PhxSQL Master的全局唯一性,保证了只存在一台MySQL被访问。从而解决了多台机器同时被读写的问题。</p> <p>PhxSQL性能</p> <p>使用sysbench工具对PhxSQL和MySQL的半同步复制进行了性能对比。PhxSQL因为增加了Phxsqlproxy,导致读性能比原生MySQL略低;但由于PhxPaxos的实现比MySQL的半同步更加高效,让PhxSQL的写性能比半同步复制更好。</p> <p>PhxSQL比MySQL读性能比原生MySQL略低,但写性能比MySQL半同步复制更好。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/c02dc340eedabcd051ab0e5a6f44ad67.png"></p> <p>测试环境和结果如下: </p> <p>机型信息</p> <p>CPU : Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz * 24</p> <p>内存 : 32G</p> <p>磁盘 : SSD Raid10</p> <p>网络互Ping耗时</p> <p>Master -> Slave : 3 ~ 4ms</p> <p>Client -> Master : 4ms</p> <p>压测工具和参数</p> <p>sysbench --oltp-tables-count=10 --oltp-table-size=1000000 --num-threads=500 --max-requests=100000 --report-interval=1 --max-time=200</p> <p>压测内容</p> <p>PhxSQL和半同步复制在Client线程200和500的环境下进行下面方式的压测:</p> <p>insert.lua (100%写)</p> <p>select.lua (0%写)</p> <p>OLTP.lua (20%写)</p> <p>压测结果</p> <p>Client线程数:200</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/078b3a6ab0382bb56574b22cc25c9e58.png"></p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/00a7a1d88956d3944fc8fc2ed0087612.png"></p> <p>Client线程数:500</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/4bc9cf2bd24a15fd4afb8862b148c9db.png"></p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/171de48049cc1f7d035093a37352525b.png"></p> <p>注:耗时分别为测试结果的平均耗时/95%分位数耗时,单位ms</p> <p>总结</p> <p>PhxSQL解决了MySQL半同步复制中数据回滚和多Master的问题,使其能实现自动Master切换且保证数据一致。PhxSQL因为增加了Phxsqlproxy,导致读性能比原生MySQL略低;但由于PhxPaxos的实现比MySQL的半同步更加高效,让PhxSQL的写性能比半同步复制更好。</p> <p> </p> <p> </p> <p>来自:http://www.dataguru.cn/article-9838-1.html</p> <p> </p>