您所在的位置:首页 > 国际 > 微信开源PhxSQL:高可用、强一致的MySQL集群

微信开源PhxSQL:高可用、强一致的MySQL集群

http://dagoum.cn | 2019/4/13 0:28:27

\

 

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 架构

 

\

 

为了解决 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 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 实现原理介绍。

 

\

 

从逻辑上来看,利用 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 管理

 

\

 

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 被访问。从而解决了多台机器同时被读写的问题。

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耗时

PhxSQL507639. 34/56.93

MySQL

半同步405549. 27/66.64

select.lua (0% 写)

QPS耗时

PhxSQL463344. 21/5.12

MySQL

半同步475284. 10/5.00

OLTP.lua (20% 写)

QPS耗时

PhxSQL25657140. 16/186.39

MySQL

半同步20391176. 39/226.76

Client 线程数:500

insert.lua (100% 写)

QPS耗时

PhxSQL826060. 41/83.14

MySQL

半同步707270. 60/91.72

-

select.lua (0% 写)

QPS耗时

PhxSQL1059284. 58/5.81

MySQL

半同步1215354. 17/5.08

-

OLTP.lua (20% 写)

QPS耗时

PhxSQL46543192. 93/242.85

MySQL

半同步33229270. 38/345.84

注:耗时分别为测试结果的平均耗时/95% 分位数耗时,单位 ms

总结

PhxSQL 解决了 MySQL 半同步复制中数据回滚和多 Master 的问题,使其能实现自动 Master 切换且保证数据一致。PhxSQL 因为增加了 Phxsqlproxy,导致读性能比原生 MySQL 略低;但由于 PhxPaxos 的实现比 MySQL 的半同步更加高效,让 PhxSQL 的写性能比半同步复制更好。

开源地址:https://github.com/tencent-wechat/phxsql

附录:

微信自研生产级 paxos 类库 PhxPaxos 实现原理介绍

微信开源C/C++ RPC 框架 PhxRPC

MySQL 半同步复制的数据一致性探讨


相关阅读:
黄金喊单 www.kztouzi.com
图片新闻
  • 张晓龙走访美国传递中国文化
  • 中国科学家发现寒武纪标志生物三叶虫的“现世亲属”
  • 网购"秒杀"为啥总抢不到?跟你竞争的可能不是"人"