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

本贴最后更新于 3006 天前,其中的信息可能已经时异事殊

PhxSQL 是由微信后台团队自主研发的一款服务高可用、数据强一致的分布式数据库服务。该服务基于 Percona5.6 搭建,目标在于解决 MySQL 在容灾和数据一致性方面的不足,并大幅简化了 MySQL 容灾切换的运维操作。

作者:Junchao Chen (junechen@tencent.com), Haochuan Cui (lynncui@tencent.com), Duokai Huang (mariohuang@tencent.com), Ming Chen (mingchen@tencent.com) 和 Sifan Liu (stephenliu@tencent.com)

总览

  • PhxSQL 具有服务高可用、数据强一致、高性能、运维简单、和 MySQL 完全兼容的特点。
  • 服务高可用:PhxSQL 集群内只要多数派节点存活就能正常提供服务;出于性能的考虑,集群会选举出一个 Master 节点负责写入操作;当 Master 失效,会自动重新选举新的 Master。
  • 数据强一致:PhxSQL 采用多节点冗余部署,在多个节点之间采用 paxos 协议同步流水,保证了集群内各节点数据的强一致。
  • 高性能:PhxSQL 比 MySQL SemiSync 的写性能更好,得益于 Paxos 协议比 SemiSync 协议更加高效;
  • 运维简单:PhxSQL 集群内机器出现短时间故障,能自动恢复数据,无需复杂的运维操作;PhxSQL 更提供一键更换(新增/删除)集群内的机器,简化运维的工作。
  • MySQL 完全兼容:PhxSQL 是基于 Percona 的研发,完全兼容 MySQL 的操作命令。 可通过 MySQL 提供的 mysqlclient/perconaserverclient 直接操作 PhxSQL。

项目中包含 PhxSQL 源代码,源代码编译时所需要的一些第三方库,及可直接在 Linux 环境下运行的二进制包。其中代码使用到了微信团队自研的另外三个开源项目(phxpaxos,phxrpc,colib)。若需编译源代码,需额外下载,也可以在 clone 时通过--recurse-submodule 获得代码。

phxpaxos 项目地址: http://github.com/tencent-wechat/phxpaxos

phxrpc 项目地址: http://github.com/tencent-wechat/phxrpc

colib 项目地址: http://github.com/tencent-wechat/libco

PhxSQL 编译

如果是直接使用二进制包,请跳过这节。

PhxSQL 主要目录结构

  • PhxSQL
    • phxsqlproxy
    • phxbinlogsvr
    • percona
    • phx_percona
      • plugin
      • phxsync_phxrpc
      • semisync
    • third_party
      • glog
      • leveldb
      • protobuf
      • phxpaxos
      • colib
      • phxrpc
    • tools
    • phxrpc_package_config

主要目录介绍

目录名
phxsqlproxy phxsqlproxy 模块,负责接入请求。
phxbinlogsvr 负责 MySQL binlog 数据同步,master 管理等。
percona percona5.6.31-77.0 的官方源代码
phx_percona/plugin/phxsync_phxrpc percona 用于跟 phxbinlogsvr 同步 binlog 的插件。
phx_percona/plugin/semisync 因兼容问题,修改了 semisync 的部分代码,目录内为修改过的文件。
third_party/glog Google Glog 第三方库
third_party/leveldb Google Leveldb 第三方库
third_party/protobuf Google Protobuf 3.0+ 第三方库
third_party/phxpaxos paxos 协议库。用于 phxbinlogsvr 之间同步 binlog
third_party/colib 协程基础库。phxsqlproxy 使用
third_party/phxrpc rpc 框架。phxbinlogsvr 使用

事前准备

安装第三方库

PhxSQL 需要用到一些第三方库(glog, leveldb, protobuf, phxpaxos, colib, phxrpc),下载后安装到 PhxSQL 的 third_party 目录下或者把安装目录链接到 PhxSQL 的 third_party 目录下。

需保证第三方库 glog, protobuf 在 configure 时带上-fPIC 选项(configure CXXFLAGS=-fPIC),并指定--prefix=当前目录绝对路径
比如 configure CXXFLAGS=-fPIC --prefix=/home/root/phxsql/third_party/glog.

下载 percona-server-5.6.31-77.0.tar.gz

percona-server-5.6\_5.6.31-77.0 源代码放到 PhxSQL 目录下,更名或链接为 percona**(请注意只能使用 percona-server-5.6_5.6.31-77.0 版本)**

生成安装环境
  1. 在 PhxSQL 目录下执行 sh autoinstall.sh && make && make install
  2. 若想打包二进制运行包(集群运行时所需要的所有文件和配置)make package
  3. install 完成后,二进制会生成到 PhxSQL 目录下的 sbin 目录,运行所需要的相关文件和配置会安装到 PhxSQL 目录下的 install_package 目录。打包二进制运行包会把 install_package 进行 tar 格式的打包,并生成 phxsql.tar.gz。若想更改 install 的安装目录,可在 sh autoinstall.sh 后加入 -prefix= 路径

PhxSQL 部署和运行

准备机器

PhxSQL 需要在 2 台或以上的机器集群上运行(建议集群内机器数目 n>=3 且 n 为奇数)

初始化 PhxSQL

  1. phxsql.tar.gz 传到集群内的所有机器,对集群内每台机器按以下步骤进行安装
    1. 解压 phxsql.tar.gz
    2. 进入 phxsql/tools, 并使用 python install.py --help 查看安装参数。(例子:python2.7 install.py -i"your_inner_ip" -p 54321 -g 6000 -y 11111 -P 17000 -a 8001 -f/tmp/data/
  2. 任意找一台机器,cd phxsql/sbin, 执行
    ./phxbinlogsvr_tools_phxrpc -f InitBinlogSvrMaster -h"ip1,ip2,ip3" -p 17000 (17000 为 phxbinlogsvr 监听的端口)
  3. 看到 master 初始化完成的消息后,集群即可使用。
  4. 可通过 mysql -uroot -h"your_inner_ip" -P$phxsqlproxy_port 进入 PhxSQL 执行读写操作确认 PhxSQL 已正常运行

简单测试

  1. 在 PhxSQL 目录下进入 tools 目录
  2. 执行 test_phxsql.sh port ip1 ip2 ip3, portphxsqlproxy_port, ip 为集群机器 ip

配置文件说明

PhxSQL 一共有 3 个配置文件

1. my.cnf: MySQL 的配置,请根据你的业务需求进行修改(安装前请修改 tools/etc_template/my.cnf,安装后请修改 etc/my.cnf
2. phxbinlogsvr.conf
Section name Key name comment
AgentOption AgentPort Phxbinlogsvr 监听 MySQL 访问的端口,用于 MySQL 和 binlogsvr 之间的通信
EventDataDir   Phxbinlogsvr 数据存放目录
MaxFileSize  Phxbinlogsvr 每个数据文件的大小,数据文件过大会导致启动过慢,数据文件过小会导致文件数过多,单位为 B
MasterLease Phxbinlogsv 的 master 租约时间,单位为 s
CheckPointTime Phxbinlogsvr 会删除 CheckPointTime 时间前的数据,但如果被删数据中存在其他 MySQL 还没学到的,则不会删除该部分数据,单位为分钟
MaxDeleteCheckPointFileNum  Phxbinlogsvr 删数据时,每次删除的最大文件数
FollowIP 机器为 folloer 机器,只负责拉取 FollowIP 机器上的数据,不参与集群的投票
PaxosOption PaxosLogPath Phxbinlogsvr 中 paxos 库的数据目录
PaxosPort Phxbinlogsvr 中 paxos 库的通信端口
PacketMode Phxbinlogsvr 在 paxos 协议中是否增大包的大小限制, 1 为每个包的大小为 100m,但超时限制变为 1 分钟,0 为每个包的大小为 50m,超时限制 2s 起(动态变化)
Server IP Phxbinlogsvr 的监听 ip
Port Phxbinlogsvr 的监听端口
LogFilePath Phxbinlogsvr 的日志目录
LogLevel Phxbinlogsvr 的日志级别
3. phxsqlproxy.conf
Section name Key name comment
Server IP phxsqlproxy 的监听 ip
Port phxsqlproxy 的监听端口
QSLogFilePath phxsqlproxy 的日志目录
QSLogLevel phxsqlproxy 的日志级别

PhxSQL 使用

phxsqlproxy 为 PhxSQL 的接入层,所有的请求均经过 phxsqlproxy,再透传给 MySQL。

phxsqlproxy 提供两个端口进行读写

读写端口

该端口号为 phxsqlproxy.conf 配置中的端口号, 用户连接上 proxyA 的此端口,proxyA 会自动把请求路由到 Master 机器,然后再对 Master 机器上的 MySQL 进行操作。

只读端口

该端口号为读写端口号 +1, 用户连接上此端口时,会对本机的 MySQL 进行操作(但若本机为 master,则 phxsqlproxy 会把请求转发到其他 phxsqlproxy 的只读端口)。

PhxSQL 的使用

  1. 通过 mysql 命令连接上 phxsqlproxy,然后执行命令 mysql -uroot -h$phxsqlproxyip -P$phxsqlproxyport -ppwd
  2. 进行 sql 命令操作

phxsqlproxyip 为集群内的任意一台 phxsqlproxy 的 ip

phxsqlproxyport 为 phxsqlproxy 端口(读写/只读)

PhxSQL 管理

PhxSQL 提供一个工具 phxbinlogsvr_tools_phxrpc 来方便管理者对 PhxSQL 的运营管理。

PhxSQL 集群中对 MySQL 的管理使用两个账号管理员帐号和数据同步账号。管理员账号默认账号密码为("root",""),数据同步账号默认账号密码为("replica","replica123")。账号密码的更改通过工具才执行(工具会直接操作 MySQL 数据,不需要人工进行 MySQL 操作)。

phxbinlogsvr_tools -f GetMasterInfoFromGlobal -h <host> -p <port>

**功能:**集群的 master 机器 ip 和超时时间

参数:

  • Host: 集群中的其中一台机器 ip
  • Port: phxbinlogsvr 的监听 port

phxbinlogsvr_tools -f SetMySqlAdminInfo -h <host> -p <port> -u <admin username> -d <admin pwd> -U <new admin username> -D <new admin pwd>

功能: 设置 PhxSQL 管理员账号密码

参数:

  • Host: 集群中的其中一台机器 ip
  • Port: phxbinlogsvr 的监听 port
  • Admin username: 当前的管理员账号(默认为 root)
  • Admin pwd: 当前的管理员密码(默认为空)
  • New admin username: 新的管理员账号
  • New admin pwd: 新的管理员密码

phxbinlogsvr_tools -f SetMySqlReplicaInfo -h <host> -p <port> -u <admin username> -d <admin pwd> -U <new replica username> -D <new replica pwd>

功能: 设置 PhxSQL 同步数据账号密码

参数:

  • Host: 集群中的其中一台机器 ip
  • Port: phxbinlogsvr 的监听 port
  • Admin username: 当前的管理员账号(默认为 root)
  • Admin pwd: 当前的管理员密码(默认为空)
  • New replica username: 新的同步数据账号
  • New replica pwd: 新的同步数据密码

phxbinlogsvr_tools_phxrpc -f GetMemberList -h <host> -p <port>

**功能:**集群的 master 机器 ip 和超时时间

参数:

  • Host: 集群中的其中一台机器 ip
  • Port: phxbinlogsvr 的监听 port

phxbinlogsvr 成员管理

移除成员

执行工具命令将机器 A 移除集群 phxbinlogsvr_tools_phxrpc -f RemoveMember -h<host> -p<port> -m <机器A的ip>

执行成功后,机器 A 将会在一段时间后不在接收数据

添加成员

  1. 执行工具将机器 A 加入到集群 phxbinlogsvr_tools -f AddMember -h<host> -p<port> -m <机器A的ip>

  2. 在新机器 A 上安装好 PhxSQL

    根据 "初始化PhxSQL" 步骤安装 PhxSQL

  3. 执行成功后,机器 A 的 phxbinlogsvr 将会在一段时间后开始接收数据

  4. 从集群内任意一台机器的 percona 导出一份镜像数据

  5. kill 掉机器 A 上的 phxbinlogsvr, 并通过本地的 MySQL 端口进入 MySQL,执行 set super_read_only = 0; set read_only = 0;

  6. 将镜像数据导入到机器 A 上的 percona,并 kill 掉机器 A 上的 phxbinlogsvr

  7. 一段时间(~1 分钟)后,机器 A 开始正常工作

phxbinlogsvr 故障处理

当机器出现问题,PhxSQL 无法正常启动时,可以选择在该机器上重装 PhxSQL,重装过程可参考 4.2

在重装过程中,phxbinlogsvr 可能会拉取集群内其他机器 checkpoint 来启动,待 checkpoint 拉取结束后,phxbinlogsvr 会自杀(为了确保数据安全),日志中会出现 "All sm load state ok, start to exit process",此时须重新启动 phxbinlogsvr,启动后会正常运行。

当 MySQL 数据出现问题时,phxbinlogsvr 会停止工作,此时需要检查 MySQL 的 binlog 数据是否正常。
当出现问题时,可观察日志中带有 err 标志的红色字体的日志,来确认是否有异常。

性能测试

机型信息

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

压测结果

Client 线程数 测试集群 测试集合
insert.lua (100% 写) select.lua (0% 写) OLTP.lua (20% 写)
QPS 耗时 QPS 耗时 QPS 耗时
200 PhxSQL 5076 39.34/56.93 46334 4.21/5.12 25657 140.16/186.39
200 MySQL 半同步 4055 49.27/66.64 47528 4.10/5.00 20391 176.39/226.76
500 PhxSQL 8260 60.41/83.14 105928 4.58/5.81 46543 192.93/242.85
500 MySQL 半同步 7072 70.60/91.72 121535 4.17/5.08 33229 270.38/345.84
注:耗时分别为测试结果的平均耗时/95% 分线耗时,单位 ms
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    342 引用 • 708 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • R
    作者

    😃

  • 其他回帖
  • tmedivh

    这个确实不错啊

  • Angonger

    我以为你做了个微信机器人

    1 回复
  • tmedivh

    不错啊 啊啊啊啊啊啊啊啊