社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

ProxySQL + MySQL MGR读写分离架构的Sysbench只读压测报告

InfoQ • 4 年前 • 467 次点击  

作者 | 雷宏婧
编辑 | 冬梅
在大量并发读请求、读多写少的业务场景下,本文利用 Sysbench 性能测试工具,调研基于【负载均衡 + ProxySQL Cluster + MySQL MGR 的读写分离架构】能否有效利用横向扩展的 MySQL 实例的读能力,并最终提高应用系统 QPS。
前    言

在大量并发读请求、读多写少的业务场景下,本文利用 Sysbench 性能测试工具,调研基于【负载均衡 + ProxySQL Cluster + MySQL MGR 的读写分离架构】能否有效利用横向扩展的 MySQL 实例的读能力,并最终提高应用系统 QPS。

  1. MySQL Group Replication(MGR)于 2016 年 12 月被推出,提供了高可用、高扩展、高可靠的 MySQL 集群服务。但其仅解决了数据同步问题和集群内部的自动故障转移。当 Master 宕机,应用系统可能需要修改数据库连接地址,才能保证服务的可用性。为解决上述问题,可在 MRG 上层增加代理层,例如 ProxySQL。

  2. ProxySQL 于 2015 年被推出,是一个开源、高性能、高可用性、协议感知的 MySQL 代理。

    1) 可通过每个节点的 read_only 值,自动调整它们是属于读组还是写组;

    2) 可定制基于用户、基于 schema、基于语句的规则对 SQL 语句进行路由,实现读写分离;

    3) 支持搭建 ProxySQL Cluster 来达到高可用,节点之间的配置可自动同步。

  3. 负载均衡是将流量分发至多台节点设备上处理的服务。

    1) 可通过消除单点故障,提升应用系统的可用性;

    2) 可减缓大量的并发访问,提高应用系统的处理能力。

  4. Sysbench 是一个开源的、模块化的、跨平台的多线程性能测试工具。

1. 压测目的

基于 Sysbench 的 oltpreadonly 压测模式,对比【负载均衡 + ProxySQL Cluster + MGR 的读写分离】和【应用直连 MySQL Master】这两种架构的只读性能:

  1. 建立读写分离架构的只读性能基线数据;

  2. 验证读写分离架构在大量并发读请求场景下的有效性;

  3. 分析各模块和参数对读写分离架构性能的影响。

2. 压测结论
2.1. 读写分离架构的只读性能基线数据

在 Sysbench oltpreadonly 压测模式下,【4 层负载均衡 +ProxySQL Cluster+MGR 读写分离】架构的 QPS 与并发线程数关系如下表所示。

ps:“/”表示由于 Sysbench 机器 CPU 耗尽,未能完成测试,无实验结果。

2.2. 只读场景下读写分离架构的有效性

首先简单浏览下实验对比架构和结果,



ps:“/”表示由于 Sysbench 机器 CPU 耗尽,未能完成测试,无实验结果。实验结果表明:

  1. 在不引入负载均衡、ProxySQL Cluster 等中间件的理想情况下,【应用直连 MGR 2 个只读实例】QPS 最大值能达到 100w,为【应用直连 MySQL Master】的只读 QPS 最大值 37w 的 2.7 倍。该结果验证了 MGR 架构在大量并发读请求场景下的有效性。

但实际上,如要保证应用系统高可用,则需引入负载均衡、ProxySQL Cluster 等中间件,而这些中间件或多或少会带来性能损失。实验发现,【4 层负载均衡 +ProxySQL Cluster+MGR 读写分离】架构的只读 QPS 最大值为 89w,约为【应用直连 MySQL Master】的只读 QPS 最大值 37w 的 2.4 倍,该结果验证了【4 层负载均衡 +ProxySQL Cluster+MGR 读写分离】架构在大量并发读请求场景下的有效性。

2.3. 各模块和参数对读写分离架构性能的影响

  1. 【4 层负载均衡 +ProxySQL Cluster+MGR 读写分离】架构的 QPS 最大值约为【直连 MGR 2 个只读实例】QPS 最大值 100w 的 89%。其中,ProxySQL Cluster 带来约 11% 的性能损失,负载均衡几乎没有带来性能损失。但是 ProxySQL 的 CPU 占用率最高仅 57%,还需后续探索能否进一步有效利用 ProxySQL。

  2. 根据 https://github.com/sysown/ProxySQL/issues/1724,参考 CPU 核数增加 ProxySQL 的 mysql-threads 变量值,即增加 ProxySQL 用于处理 MySQL 流量的后台线程数,能有效提升 QPS(如将线程数从 4 增加至 16,QPS 提升了 3.3 倍),但目前还没压测出 ProxySQL 的 CPU 利用率提升到 100% 的场景。

  3. 横向拓展 ProxySQL 实例数目,能有效提升 QPS(实例数从 1 增加至 2,QPS 提升 1 倍)。

  4. 将 7 层负载均衡换成 4 层,由在应用层进行流量分发改成在传输层,降低网络性能损耗,在实验中提升了 1 倍 QPS。

  5. 根据 https://ProxySQL.com/blog/benchmarking-ProxySQL-144/,增大 ProxySQL 的 mysql-max_stmts_per_connection 变量值(20 增加至 100),让单个连接可以处理更多的 prepared 语句,但实验中未能影响 QPS。

3. 压测详情
3.1. 压测环境

此外,还安装了 nodeexporter、mysqlexporter、proxysql_exporter 来监控 OS、MySQL 和 ProxySQL,方便定位问题。

3.2. 压测指标
  • 每秒执行请求数 QPS(Queries Per Second)数据库每秒执行的 SQL 数,包含 INSERT、SELECT、UPDATE、DETELE、COMMIT 等。QPS 值越高越好。

  • 95% Latency (ms) 95% 请求的延迟时间表征的是全部 query 请求中的 95% 在发出至收到结果的平均往返时间。延迟越小越好。

3.3. 实验设置

为减少误差,每轮实验重复 3 次。每次任务执行完之后,等待 300s,让系统及时处理未完成任务,才进入下一轮压测。压测后除了利用 Sysbench 自带的 cleanup 清理数据,还额外把 binlog 清理干净,以防磁盘空间变少而影响下一次压测。其他模块设置见下文。

3.3.1 MySQL 设置
  • MGR:单主模式。共 3 个节点,其中 1 个只写节点,2 个只读节点。max_connection 设为 3000。

  • Master-Master:主主同步,仅其中 1 个 Master 提供读写服务。max_connection 设为 3000。

3.3.2 ProxySQL 设置
  • mysql_user 表的 transaction_persistent 字段:设置为 1,表示在某节点内启动的事务将保留在该节点内,而与其他转发规则无关。用于避免以下问题:一个事务有混合的读操作和写操作组成,事务未提交前,如果事务中的读操作和写操作路由到不同节点,读取到的结果是脏数据。

 insert into mysql_users(username,password,default_hostgroup,transaction_persistent) values('MGR','MGR',1,1);
  • mysql_servers 表的 max_connections:允许连接到该后端实例的最大连接数,不能大于 MySQL 设置的 max_connections,因此设为 3000。

  • mysql_group_replication_hostgroups 表:配置 MGR writerhostgroup、readerhostgroup 等组别对应的 hostgroupid。ProxySQL 会通过视图来监控 MGR 节点是否正常,是否开启了只读、挤压事务数等来调整单个 MGR 节点所属的 hostgroupid,具体调整结果可在 runtime_mysql_servers 中查看。    insert into mysql_group_replication_hostgroups(writer_hostgroup,backup_writer_hostgroup,reader_hostgroup,offline_hostgroup,active,max_writers,writer_is_also_reader,max_transactions_behind,comment) values(1,2,3,4,1,1,0,100,'mgr-test');

    -- 可以看出有写组有 1 个节点,读组有 2 个节点,均在正常工作

  • 查询规则配置:根据 SQL 的正则表达式匹配,读请求转发至读组,写请求转发至写组。

-- 将写请求转发到写组

INSERT INTO mysql_query_rules (rule_id,active,username,match_digest,destination_hostgroup,apply) VALUES (200,1,'mgr','^SELECT.*FOR UPDATE$',1,1);

-- 将读请求转发到读组

INSERT INTO mysql_query_rules (rule_id,active,username,match_digest,destination_hostgroup,apply) VALUES (201,1,'mgr','^SELECT',3,1);

  • 全局变量 mysql-threads:是 ProxySQL 用于处理 MySQL 流量的后台线程数。默认值为 4,实验中发现,增加值至 16 可大幅提升 QPS,因此除了该变量的参数调优实验,其他实验中该变量值均为 16。    

set mysql-threads=16;show variables like 'mysql-threads';

3.3.3 Sysbench 设置
  • 实验基于 Sysbench 的 oltpreadonly 只读模式。该模式下,一个事务包含 14 个读 SQL(10 条主键点查询、4 条范围查询)。

  • oltpreadonly 模式的压测命令

准备数据:

sysbench --db-driver=mysql --mysql-host=XXX --mysql-port=XXX --mysql-user=XXX --mysql-password=XXX --mysql-db=dbtest --tables=1 --table-size=10000000 --report-interval=1 --threads=XXX --rand-type=uniform --time=120 --auto-inc=on /usr/local/share/sysbench/oltp_read_only.lua prepare

运行 workload:

sysbench --db-driver=mysql --mysql-host=XXX --mysql-port=XXX --mysql-user=XXX --mysql-password=XXX --mysql-db=dbtest --tables=1 --table-size=10000000 --report-interval=1 --threads=XXX --rand-type=uniform --time=120 --auto-inc=on --skip_trx=on /usr/local/share/sysbench/oltp_read_only.lua run

清理数据:

sysbench --db-driver=mysql --mysql-host=XXX --mysql-port=XXX --mysql-user=XXX --mysql-password=XXX --mysql-db=dbtest --tables=1 --table-size=10000000 --report-interval=1 --threads=XXX --rand-type=uniform --time=120 --auto-inc=on /usr/local/share/sysbench/oltp_read_only.lua cleanup

普通变量:

  • time:压测总持续时间(秒),超时后任务未完也会被终止。

  • threads:并发压测的线程数。取值范围[16,32,64,128,256,512,1024,1500,2048,2500,3000,3500,4096]。

重点变量:

  • skip_trx[=on|off]:默认为 off,即启动显式事务;值为 on 时,不启动显式事务,以 AUTOCOMMIT 模式执行所有查询。

  • 压测时设置:sysbench --skiptrx=on;ProxySQL 的 mysqluser 表的 transaction_persistent=1。原因如下:

  • ProxySQL 的 mysqluser 表的 transactionpersistent 字段设为 1 时,在某节点内启动的事务将保留在该节点内,而与其他转发规则无关。用于避免以下问题:一个事务有混合的读操作和写操作组成,事务未提交前,如果事务中的读操作和写操作路由到不同节点,读取到的结果是脏数据。因此,如果不开启 skip_trx,sysbench 所有请求都会被 ProxySQL 转发到写组,如此便测不了读写分离的性能。

  • sysbench 默认使用 prepared statements,因本实验需要测试使用 prepared statements 的情况,故在此不作关闭该功能的参数说明。

  • 设置变量 --mysql-host=[host1,host2,...,hostN],即可对多个 MySQL 同时发起读请求。可用于并发压测多个 MySQL 实例时的 QPS。

https://github.com/akopytov/sysbench/issues/19

3.3.4 实验场景设置

总共设计了 6 个实验场景(架构图详见实验结果分析),实验目的如下:

3.4. 实验结果分析
实验 1: [MGR] vs [Master-Master]

实验目的:

获取通过应用(sysbench)直连 MGR 的 2 个只读实例数所能带来的 QPS 上限,确认该上限和应用直连 mysql Master-Master 中其中 1 台的 QPS 差异。

实验结果:



ps:“/”表示由于 Sysbench 机器 CPU 耗尽,未能完成测试,无实验结果。

  • MGR QPS 上限约 100w,约为 Master-Master 的 2.67 倍。

实验 2: [single ProxySQL+MGR] vs [MGR]

实验目的:

在尽可能减少应用和 ProxySQL 之间网络延迟的情况下,确认增加 ProxySQL 中间件会带来的性能损失

实验结果:



ps:“/”表示由于 Sysbench 机器 CPU 耗尽,未能完成测试,无实验结果。

  • single ProxySQL+MGR QPS 最大 48w,约为 MGR 的 48%。

  • single ProxySQL+MGR QPS 最大时,ProxySQL 实例 CPU 占用率最高为 57%。

实验结论:

在该实验中,ProxySQL Cluster 带来约 48% 的性能损失,但此时 ProxySQL 的 CPU 占用率并不算很高,值得后续探索能否进一步有效利用 ProxySQL。

实验 3: [ProxySQL Cluster+MGR] vs [single ProxySQL+MGR]


实验目的:

确认横向拓展 ProxySQL 实例数目能否进一步提升 QPS

实验结果:



ps:“/”表示由于 Sysbench 机器 CPU 耗尽,未能完成测试,无实验结果。

  • ProxySQL Cluster+MGR QPS 上限约 89w,约为 single ProxySQL+MGR 的 1.85 倍。

  • ProxySQL Cluster+MGR QPS 最大时,ProxySQL 实例 CPU 占用率最高为 56%。

实验结论:

横向拓展 ProxySQL 实例数目可以进一步提升 QPS 至 89w,相对接近 MGR 的上限 100w。

实验 4: [7 层负载均衡 +ProxySQL Cluster+MGR] vs [ProxySQL Cluster+MGR]


实验目的:

增加读写分离架构中必不可少的负载均衡服务,并确认其带来的性能损失

实验结果:



ps:“/”表示由于 Sysbench 机器 CPU 耗尽,未能完成测试,无实验结果。

  • 增加负载均衡后,QPS 最大值为 42w,约 MGR 上限的 50%,仅为 Master-Master 的 1.135 倍。

实验结论:

增加负载均衡导致性能损失近 50%,可能是因为网络、配置问题,需要进一步排查。

实验 5: [4 层负载均衡 +ProxySQL Cluster+MGR] vs [7 层负载均衡 +ProxySQL Cluster+MGR]

实验目的:

4 层负载均衡工作在 OSI 模型的传输层(基于 IP+ 端口),7 层工作在应用层(基于 URL)。

理论上,7 层负载均衡会带来更多的网络性能损耗。因此尝试调整为 4 层负载均衡,以减少性能损失。

实验结果:



ps:“/”表示由于 Sysbench 机器 CPU 耗尽,未能完成测试,无实验结果。

实验结论:

将 7 层负载均衡换成 4 层负载均衡后,QPS 最大值为 89w,负载均衡几乎没带来性能损失。

实验 6: ProxySQL 参数调优:分析 mysql-threads 参数值对性能的影响

实验目的:

根据https://github.com/sysown/ProxySQL/issues/1724,mysql-threads 变量是 ProxySQL 用于处理 MySQL 流量的后台线程数,理论上,根据机器 CPU 核数来调整该变量,可提升 ProxySQL 性能。因此尝试分析该参数对性能的影响。

实验结果:



ps:“/”表示由于 Sysbench 机器 CPU 耗尽,未能完成测试,无实验结果。

实验结论:

根据机器 CPU 核数来增加 ProxySQL 的 mysql-threads 变量值,可一定程度上提升 QPS。

4. 总 结
  1. 【4 层负载均衡 + ProxySQL Cluster + MGR 读写分离】架构适用于在大量并发读请求场景,只读 QPS 最大能达到 89w,约为【应用直连 MySQL Master】的只读 QPS 最大值 37w 的 2.4 倍。

  2. 参考机器的 CPU 核数增加 ProxySQL 的 mysql-threads 变量值,即增加 ProxySQL 用于处理 MySQL 流量的后台线程数,能有效提升 QPS(如将线程数从 4 增加至 16,QPS 提升了 3.3 倍)。

  3. 横向拓展 ProxySQL 实例数目,能有效提升 QPS(实例数从 1 增加至 2,QPS 提升 1 倍)。

  4. 将 7 层负载均衡换成 4 层,由在应用层进行流量分发改成在传输层,能降低网络性能损耗并提升 QPS。

  5. 本次实验中,ProxySQL Cluster 带来约 11% 的性能损失,负载均衡几乎没有带来性能损失。但是 ProxySQL 的 CPU 占用率最高仅 57%,还需后续探索能否进一步有效利用 ProxySQL。

参考文献:

  1. https://dev.MySQL.com/doc/refman/5.7/en/group-replication.html

  2. https://ProxySQL.com/documentation/ProxySQL-Threads/

  3. https://ProxySQL.com/blog/ProxySQL-vs-maxscale-persistent-connection-response-time/

  4. https://www.percona.com/blog/2020/08/28/ProxySQL-overhead-explained-and-measured/

  5. https://github.com/sysown/ProxySQL/issues/1724

  6. https://www.percona.com/blog/2017/04/10/ProxySQL-rules-do-i-have-too-many/

作者简介:

雷宏婧,网易游戏 技术部高级数据库系统工程师。参与海量玩家数据库生产环境故障排查和优化,热衷于研究MySQL技术原理、灾难备份和高可用方案。

今日好文推荐

独家专访腾讯云CTO王慧星:云技术变革上下二十年

数据中台与湖仓一体能碰出怎样的火花?网易数帆实时数据湖Arctic的新探索

流行20年的架构设计原则SOLID可能已经不适合微服务了

软件工程师年满 40 岁,下一步怎么走?



 活动推荐

InfoQ 100 位优质创作者签约计划第二季火热进行中!欢迎各位同学踊跃报名~ 签约豪华大礼包、专属身份标志、百万流量扶持等好礼,等您来拿!

活动链接:http://gk.link/a/10KyO


点个在看少个 bug 👇

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/123841