开源地址:
https://github.com/tencent-we…
点击浏览原文可主动跳转到 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 半同步复制更好。
读性能 | 写性能 | |||
---|---|---|---|---|
Client 线程数 | QPS | 耗时 | QPS | 耗时 |
200 | 约升高 3% | 耗时约减少 2% | 约增高 25% | 约升高 20% |
500 | 约升高 13% | 约减少 10% | 约增高 16% | 约升高 10% |
测试环境和后果如下:
机型信息
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
insert.lua (100% 写) | ||
---|---|---|
QPS | 耗时 | |
PhxSQL | 5076 | 39.34/56.93 |
MySQL 半同步 | 4055 | 49.27/66.64 |
select.lua (0% 写) | ||
---|---|---|
QPS | 耗时 | |
PhxSQL | 46334 | 4.21/5.12 |
MySQL 半同步 | 47528 | 4.10/5.00 |
OLTP.lua (20% 写) | ||
---|---|---|
QPS | 耗时 | |
PhxSQL | 25657 | 140.16/186.39 |
MySQL 半同步 | 20391 | 176.39/226.76 |
Client 线程数:500** |
insert.lua (100% 写) | ||
---|---|---|
QPS | 耗时 | |
PhxSQL | 8260 | 60.41/83.14 |
MySQL 半同步 | 7072 | 70.60/91.72 |
select.lua (0% 写) | ||
---|---|---|
QPS | 耗时 | |
PhxSQL | 105928 | 4.58/5.81 |
MySQL 半同步 | 121535 | 4.17/5.08 |
OLTP.lua (20% 写) | ||
---|---|---|
QPS | 耗时 | |
PhxSQL | 46543 | 192.93/242.85 |
MySQL 半同步 | 33229 | 270.38/345.84 |
注:耗时别离为测试后果的均匀耗时 /95% 分位数耗时,单位 ms
**
总结 **
PhxSQL 解决了 MySQL 半同步复制中数据回滚和多 Master 的问题,使其能实现主动 Master 切换且保证数据统一。PhxSQL 因为减少了 Phxsqlproxy,导致读性能比原生 MySQL 略低;但因为 PhxPaxos 的实现比 MySQL 的半同步更加高效,让 PhxSQL 的写性能比半同步复制更好。
开源地址:
https://github.com/tencent-we…
OpenIMgithub 开源地址:
https://github.com/OpenIMSDK/…
OpenIM 官网:https://www.rentsoft.cn
OpenIM 官方论坛:https://forum.rentsoft.cn/
更多技术文章:
开源 OpenIM:高性能、可伸缩、易扩大的即时通讯架构
https://forum.rentsoft.cn/thr…
【OpenIM 原创】简略轻松入门 一文解说 WebRTC 实现 1 对 1 音视频通信原理
https://forum.rentsoft.cn/thr…