ProxySQL 是一个开源的高性能、高可用性的 MySQL 代理,可支持,读写分离,监控,审计等功能
本次测试主要是使用ProxySQL的端口转发功能用于替代nginx
1.读写分离
1.1单个Proxy端口
| 主从关系 | 是否读写 | 地址 | 端口 | Proxy |
|---|---|---|---|---|
| 主实例 | 读写 | ops-test01.corp.cootek.com | 3310 | 6033 |
| 从实例 | 只读 | ops-test01.corp.cootek.com | 3311 |
本地连接mysql查看两个实例可发现两个server_id不同,且3311实例为只读
在ProxySQL上的管理库上配置mysql实例和路由
3310实例:接收添加,更新,删除,SELECT.*FOR UPDATE ,show 此类DML的SQL
3311实例:只接受查询SQL
使用ProxySQL连接6033进行连接操作,可以发现两条SQL分发到了3310和3311实例上了
1.2多个Proxy端口
已目前的业务场景下建议只使用一个proxy端口,原因如下:
1.即使添加从库后,只需要在proxysql中添加新从库信息,proxy会自动做路由转发。
2.如果添加新的proxy端口需要重启整个proxy。
3.只读的proxy端口指向的实例如果发生故障,会影响业务。
如果后续必须指定一个单独的只读端口,在进行测试
这里启动了6001和6002两个端口进行测试
以上会发现6001和6002均可以读写,检查一下sql路由统计表会发现insert均路由到了hostgorep=1里,select路由到了hostgorep=2里
从以上
2.高可用性
ProxySQL的高可用性只能做到将故障示例踢出集群,不能做到MHA此类的故障转移,如:
1.一主两从架构下,当主节点发生故障MHA可以自动将在两个从节点上选举出一个新主节点,并且在新主节点和剩下的从节点上搭建一个一主一从架构,以此保证高可用性。
2.ProxySQL的高可用性是指当一主两从架构下,主节点发生故障,其中一个从节点顶替主节点进行读写,当其中一个从节点有数据写入后,两个从节点数据就会不一致。
3.鉴于以上两个问题最好结合MHA和ProxySQL起来一起使用,这样可以做好,真正意义上的高可用。
4.MHA至少需要3节点架构,且需要VIP功能;出于成本考虑现在线上架构大多数均为一主一从,后续会仿造淘宝TMHA架构,使用zookeeper+ProxySQL进性测试,预计会在Q2底进行测试,如果可行将大大降低成本还有未来对数据库侧的升降配置实现无感切换
本次测试ProxySQL高可用性,以下为一主一从可能故障发生的情况
2.1单个Proxy端口主节点故障
故障模拟顺序
mysql-monitor_writer_is_also_reader=false情况下
set mysql-monitor_writer_is_also_reader=false;
load mysql variables to runtime;
1.关闭3310实例
/etc/init.d/mysql stop 3310
2.在6033对外端口上进行读写
3.观察ProxySQL日志表
select from_unixtime(time_start_us/1000/1000) as `datetime`,* from mysql_server_ping_log where ping_error is not null limit 10;
select from_unixtime(time_start_us/1000/1000) as `datetime`,* from mysql_server_connect_log where connect_error is not null order by time_start_us desc limit 10;
select from_unixtime(time_start_us/1000/1000) as `datetime`,* from mysql_server_read_only_log where error is not null limit 10;
停止3310实例后,发现写入超时失败,但是查询正常
观察ProxySQL日志
mysql-monitor_writer_is_also_reader=true 和手动设置read_only=0
set mysql-monitor_writer_is_also_reader=true;
load mysql variables to runtime;
set global read_only=0
3310实例停止后,可以正常读写,业务受影响
小结
mysql-monitor_writer_is_also_reader=false情况下
1.主节点发生故障,业务写入失败,查询正常,待主节点启动后正常写入
2.业务连接不会断开,保护了数据库长链接
mysql-monitor_writer_is_also_reader=true和手动设置read_only=0情况下
1.主节点发生故障,从节点顶替主节点进行读写,业务正常读写,不受影响
2.主节点发生故障后从节点应立即删除主从信息,防止旧主节点修复后启动有数据写入造成数据不一致
mysql-monitor_writer_is_also_reader=true时主节点发生故障不影响业务是因为,ProxySQL探测到writer不存在时,reader会变成可读可写的角色
2.2单个Proxy端口从节点故障
故障模拟顺序
mysql-monitor_writer_is_also_reader=true 情况下
1.关闭3310实例
/etc/init.d/mysql stop 3311
2.在6033对外端口上进行读写
3.观察ProxySQL日志表
select from_unixtime(time_start_us/1000/1000) as `datetime`,* from mysql_server_ping_log where ping_error is not null limit 10;
select from_unixtime(time_start_us/1000/1000) as `datetime`,* from mysql_server_connect_log where connect_error is not null order by time_start_us desc limit 10;
select from_unixtime(time_start_us/1000/1000) as `datetime`,* from mysql_server_read_only_log where error is not null limit 10;
停止3311实例后,读写正常。业务不受影响
小结
1.从节点不可用时,读写不受影响,业务不会受到影响
2.3单个Proxy端口主从节点同时发生故障
3310和3311示例停止后,读写均失效
2.4多个Proxy端口从节点故障
从节点故障后6002端口不可用,当从节点恢复启动后才可以正常使用
2.5多个Proxy端口主节点故障
当主节点故障时,两个端口仅有6002可读,其余功能均失效;主节点恢复后读写功能均恢复
要是需要将故障转移需要将从节点设置read_only=0
总结
从单个Proxy端口和多个Proxy端口测试结果上看,优缺点如下:
| 优点 | 缺点 | |
|---|---|---|
| 单个Proxy端口 | 1.单个端口也可实现读写分离2.主从任一节点均可以快速故障转移(需要手动修改read_only)3.即使有先节点添加需要添加到mysql_servers和mysql_query_rules中 | 1.单点的端口下,如果业务强制需要只读端口,则无法提供2.相对的端口扩展性较小3.不能做到全自动高可用 |
| 多个Proxy端口 | 1.多个端口实现读写分离2.读写分离配置清晰3.主从任一节点均可以快速故障转移(需要手动修改read_only=1) | 1.从节点故障会导致查询业务失效2.添加多个只读端口需要重启ProxySQL3.增加维护成本4.使用只读端口可以做写操作,后端会自动转换到主库(会迷惑人)4.不能做到全自动高可用 |
建议:虽然以上的两种情况都可以快速做到故障转移,都是手动修改read_only,最好添加上一个可靠的探活服务,当探测到故障自动修改(推荐zookeeper)
3.监控功能
3.1探活功能
SELECT hostname,port,avg(ping_success_time_us),ping_error FROM monitor.mysql_server_ping_log group by port ORDER BY time_start_us DESC ;
可计算出ProxySQL到mysql的ping延迟
4.集群功能
当前集群已在ops-test01.corp.cootek.com,172.30.0.2上进行配置,集群信息如下
| 地址 | 管理端口 | 对外端口 |
|---|---|---|
| ops-test01.corp.cootek.com | 6000 | 6001,6002 |
| ops-test01.corp.cootek.com | 7000 | 7001,7002 |
| 172.30.0.2 | 6000 | 6001,6002 |
以上做DML可以发现均可得到一样的结果,一下对集群中的任意节点进行删除,踢出ops-test01.corp.cootek.com:7000节点
在ops-test01.corp.cootek.com:6000踢出ops-test01.corp.cootek.com:7000
172.30.0.2:6000上看数据也已经同步完成
4.1集群配置检查
select * from stats_proxysql_servers_checksums order by name ;
如果diff_check字段不为0则表示配置信息没有同步
总结:ProxySQL集群配置流程简单,唯一麻烦的一点就是在新增集群时,需要从已有的集群中拷贝数据到新集群中,类似mysql搭建主从,先恢复备份在同步
5.审计功能
审计日志仅支持json格式,日志最小1M最大1G,达到最大限度后将切割,但是开启审计会消耗性能需要注意,建议只在只在重点项目开启,而且日志量非常大
如需简单统计stats_mysql_query_digest表基本可以实现
以下为日志内容,记录了mysql模块的 成功认证、认证失败、正常断开、封闭连接、更改架构
有个小问题就是管理模块的日志没发现记录(不确定是否会将mysql模块和管理模块的区分开,因为在测试时发现管理模块的日志没变化),后续在测试
6.其他功能
1.连接延迟计算
select hostname,port,avg(connect_success_time_us),connect_error from monitor.mysql_server_connect_log group by port ORDER BY time_start_us DESC;
2.主从延迟计算
SELECT hostname,port,FROM_UNIXTIME(time_start_us/1000000 + 8 * 3600) as time_start_us,repl_lag FROM monitor.mysql_server_replication_lag_log where port='3311' ORDER BY time_start_us DESC limit 20;
3.SQL统计
总执行时间查找前 5 个查询:
SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' ORDER BY sum_time DESC LIMIT 5;
根据计数查找前 5 个查询:
SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' ORDER BY count_star DESC LIMIT 5;
根据最大执行时间查找前 5 个查询:
SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time,sum_time/count_star avg_time, min_time, max_time FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' ORDER BY max_time DESC LIMIT 5;
4.远程管理ProxySQL
set admin-admin_credentials='admin:********;remoteadmin:********';
load admin variables to runtime;
save admin variables to disk;
admin账号默认只能本地连接,需要新创建远程管理账号