【重磅】微信开源 PhxSQL:高可用、强一致的 MySQL 集群
开源地址:
https://github.com/tencent-wechat/phxsql
点击阅读原文可自动跳转到 github 地址
PhxSQL 是一个兼容 MySQL、服务高可用、数据强一致的关系型数据库集群。PhxSQL 以单 Master 多 Slave 方式部署,在集群内超过一半机器存活的情况下,可自身实现自动 Master 切换,且保证数据一致性。
****
PhxSQL 基于 Percona 5.6 开发。Percona 是 MySQL 的一个分支,功能和实现与 MySQL 基本一致。因此本文后续直接把 MySQL 作为讨论对象。
MySQL 半同步复制存在缺陷,在 Master 进行切换的场景下,数据难以保证一致。
当旧 Master 复制失败时,旧 Master 和 Updated Slave(已收到 Binlog 的 Slave)需要回滚数据。
当 Master 进行切换时,旧 Master 仍有部分 Client 进行读写。
关于 MySQL 半同步复制的数据一致性问题可查看微信后台团队公众号文章MySQL半同步复制的数据一致性探讨。
PhxSQL 的设计是为了解决 MySQL 半同步复制的不足,使 MySQL 集群在 Master 切换过程中保证数据的一致。
*PhxSQL 架构
图 1 PhxSQL 三层架构
为了解决 MySQL 的两个问题(Binlog 复制和 Master 切换),PhxSQL 设计了两个模块(Phxbinlogsvr、Phxsqlproxy)和一个 MySQL 插件(Phxsync)。Phxbinlogsvr 负责处理 MySQL 的 Binlog 复制和 Master 管理;Phxsqlproxy 负责透传 Client 请求到 Master;Phxsync 插件负责 MySQL 和 Phxbinlogsvr 的交互。 一台部署了 Phxsqlproxy,MySQL 和 Phxbinlogsvr 的机器称为 PhxSQL Node。如图 1。
PhxSQL 复制流程
图 2.1 MySQL 复制流程
图 2.2 PhxSQL 复制流程
图 2 MySQL 和 PhxSQL 的数据复制流程
在 PhxSQL 中,Phxbinlogsvr 负责管理 MySQL 的角色和存储 MySQL 的 Binlog,Phxbinlogsvr 和其管理的 MySQL 部署在同一台物理机上。
MySQL Master 在 Send Event 阶段不再把 Binlog 复制给 Slave,而是通过 Phxsync 插件,把数据复制到 Phxbinlogsvr 集群。
MySQL Slave 也不再从 Master 获取 Binlog,而是从本机的 Phxbinlogsvr 获取。
Phxbinlogsvr 集群使用 Paxos 协议进行数据复制。
PhxSQL 使用 PhxPaxos 库,详情请查看微信后台团队公众号文章微信自研生产级paxos类库PhxPaxos实现原理介绍。
图 3 Phxbinlogsvr 形成一个可靠日志存储
图 4 重启向 Phxbinlogsvr 询问 PendingBinlog 状态
从逻辑上来看,利用 Paxos 协议进行复制,使 Phxbinlogsvr 形成一个可靠的日志存储。PhxSQL 可以看成是为 MySQL 增加了一个用 Paxos 实现的可靠 Binlog 存储,只要集群中多数派机器存活,就可以解决半同步复制的回滚问题。如图 3。
分别从 Master 和 Slave 的角度来解释:
Master 重启时,通过询问 Phxbinlogsvr(多数派)Pending Binlog 是否存在来决定是否需要回滚。如图 4。
Slave 从本机 Phxbinlogsvr 能拉取到的 Binlog 都已经经过 Paxos 协议成功复制到多数派机器,因此对于 Slave 来说不存在回滚的问题。
Phxbinlogsvr 通过 Paxos 协议复制数据,很好的解决了 MySQL 中需要手动回滚 Binlog 和在大集群时同时需要回滚 Updated Slave 上的 Binlog 的问题。
PhxSQL 的 Master 管理
图 5 多个 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 之后仍然保证集群内各机数据一致。
图 6
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 读取数据,导致读不到最新的数据。
图 7
上述两个问题都是由于 MySQLClient 的 Master 信息更新不及时;部分 Client 没有及时更新,使得有可能产生 PhantomRead(两次读的结果不一致)。
图 8 Phxsqlproxy 的请求透传
若 Slave 机器被访问,Phxsqlproxy 则会把请求透传到 Master 机器的 Phxsqlproxy。由于 PhxSQL Master 的全局唯一性,保证了只存在一台 MySQL 被访问。从而解决了多台机器同时被读写的问题。
PhxSQL 性能
使用 sysbench 工具对 PhxSQL 和 MySQL 的半同步复制进行了性能对比。PhxSQL 因为增加了 Phxsqlproxy,导致读性能比原生 MySQL 略低;但由于 PhxPaxos 的实现比 MySQL 的半同步更加高效,让 PhxSQL 的写性能比半同步复制更好。
PhxSQL 比 MySQL 读性能比原生 MySQL 略低,但写性能比 MySQL 半同步复制更好。
测试环境和结果如下:
机型信息
CPU : Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz * 24
内存 : 32G
磁盘 : SSD Raid10
网络互 Ping 耗时
Master -> Slave : 3 ~ 4ms
Client -> Master : 4ms
压测工具和参数
sysbench --oltp-tables-count=10 --oltp-table-size=1000000 --num-threads=500 --max-requests=100000 --report-interval=1 --max-time=200
压测内容
PhxSQL 和半同步复制在 Client 线程 200 和 500 的环境下进行下面方式的压测:
insert.lua (100%写)
select.lua (0%写)
OLTP.lua (20%写)
压测结果
Client 线程数:200
注:耗时分别为测试结果的平均耗时/95%分位数耗时,单位 ms
**总结**
PhxSQL 解决了 MySQL 半同步复制中数据回滚和多 Master 的问题,使其能实现自动 Master 切换且保证数据一致。PhxSQL 因为增加了 Phxsqlproxy,导致读性能比原生 MySQL 略低;但由于 PhxPaxos 的实现比 MySQL 的半同步更加高效,让 PhxSQL 的写性能比半同步复制更好。
开源地址:
https://github.com/tencent-wechat/phxsql
OpenIMgithub 开源地址:
https://github.com/OpenIMSDK/Open-IM-Server
**OpenIM 官网 :**https://www.rentsoft.cn
**OpenIM 官方论坛:**https://forum.rentsoft.cn/
更多技术文章:
开源 OpenIM:高性能、可伸缩、易扩展的即时通讯架构https://forum.rentsoft.cn/thread/3
【OpenIM 原创】简单轻松入门 一文讲解 WebRTC 实现 1 对 1 音视频通信原理https://forum.rentsoft.cn/thread/4
评论