ProxySQL 安装配置详解及读写分离、负载均衡
前言
在MySQL的高可用集群环境中,中间件是不可缺少的一部分,它提供了读写分离、负载均衡等各种功能,满足集群的横向、纵向的可扩展。由于官方并没有在这方面推出好的产品,更多的是第三方的产品。如:
- ProxySQL #Percona
- MaxScale #MariaDB
- Atlas #360开源
- OneProxy #平民软件楼方鑫
- MyCat #社区推广
- KingShard #原Atlas作者离职后使用go开发
- TDDL #阿里巴巴开源
- Cobar #阿里巴巴开源
- DBProxy #美团在360Atlas上修改后开源
- Fabric #官方产品
- DRDS #阿里云分库分表产品
本次以测试ProxySQL为例,逐步了解ProxySQL的使用方式。
准备
环境:
ProxySQL: 1.4.1
Master: 118.190.67.67
Slave: 139.196.95.103(192.168.7.50)
安装配置详解
官网:http://www.proxysql.com/
Percona地址:https://www.percona.com/downloads/proxysql/
Github地址:https://github.com/sysown/proxysql/
本文通过作者编译好的rpm安装,也可通过编译安装的方式安装,本文省略
安装
下载proxysql可以有三种途径,分别为官网、Percona网站和Github网站
本文从github上下载最新稳定版本,这里选择centos67对应的rpm包
下载:wget -c -O proxysql-1.4.1-1-centos67.x86_64.rpm https://github.com/sysown/proxysql/releases/download/v1.4.1/proxysql-1.4.1-1-centos67.x86_64.rpm
[root@iZuf6c08fdv8duubho2b0rZ test]# yum localinstall -y proxysql-1.4.1-1-centos67.x86_64.rpm |
ProxySQL默认配置文件为/etc/proxysql.cnf,只在第一次启动的时候有用,后续的所有配置都是通过对SQLite数据库的操作,并且不会更新到proxysql中,而是存储在/var/lib/proxysql/proxysql.db中
[root@jiessie test] |
启动
启动之后才会生成存储目录/var/lib/proxysql
[root@jiessie test]# /etc/init.d/proxysql start |
内置对象介绍
登录
启动了6032和6033两个端口,默认管理端口是6032,客户端服务端口是6033,默认的用户名密码都是 admin,通过mysql的客户端可以登录
[root@jiessie test]# netstat -tunlp|grep proxysql |
内置库
main:默认数据库名,用于存放后端db实例、用户认证、路由规则等信息。表名以runtime_开头的表示proxysql当前运行的配置内容,不能通过dml语句修改。只能修改对应的不以runtime_开头的(在内存)里的表,然后LOAD使其生效,SAVE使其存到硬盘以供下次重启加载。
disk:是持久化到硬盘的配置,sqlite数据文件。
stats:是proxysql运行抓取的统计信息,包括到后端各命令的执行次数、流量、processlist、查询各类汇总、执行时间等。
monitor:库存储monitor模块收集的信息,主要是对后端db的健康、延迟检查。
main库
runtime_表
MySQL [main] 17:19:10 > use main |
其中,runtime_开关的表如下:
- runtime_global_variables:global_variables的运行时版本
- runtime_mysql_group_replication_hostgroups:mysql_group_replication_hostgroups的运行时版本
- runtime_mysql_query_rules:mysql_query_rules的运行时版本
- runtime_mysql_replication_hostgroups:mysql_replication_hostsgroups的运行时版本
- runtime_mysql_servers:mysql_servers的运行时版本
- runtime_mysql_users:mysql_users的运行时版本
runtime_scheduler:scheduler调度程序的运行时版本
global_variables表
内置参数表,参考下文
mysql_servers表
MySQL [main] 17:22:16 > show create table mysql_servers\G |
hostgroup_id:ProxySQL通过hostgroup的形式组织后端db实例,一个hostgroup代表同属于一个角色。
表的主键是(hostgroup_id, hostname, port),以hostname:port在多个hostgroup中存在。
一个hostgroup可以有多个实例,即是多个从库,可能通过weight分配权重。
hostgroup_id 0是一个特殊的hostgroup,路由查询的时候,没有匹配到规则则默认选择hostgroup 0。
ONLINE:当前后端实例状态正常。
SHUNNED:临时被剔除,可能因为后端too many connection error,或者超过了max_replication_lag。
OFFLINE_SOFT:软离线状态,不再接受新的连接,但已建立的连接会等待活跃事务完成。
OFFLINE_HARD:硬离线状态,不再接受新的连接,已建立的连接或被强制中断,当后端实例宕机或网络不可达,会出现。
如果后端实例hostname:port在多个hostgroup里,以较大者为准,而不是各自独立允许的最大连接数。
其他的字段,可通过字面意思理解。
mysql_users表
MySQL [main] 09:13:02 > show create table mysql_users\G |
username,password:连接到后端MySQL或ProxySQL实例的凭证,参考密码管理。
密码可插入明文,也可通过PASSWORD()插入密文,proxysql以*开头判断插入是否是密文。
但是runtime_mysql_users里统一是密文,所以明文插入,再SAVE MYSQL USERS TO MEM,此时看到的也是HASH密文。
默认为NULL,实际上受变量mysql-default_schema的影响,默认为information_schema。
backend:如果设置为1,则用户名、密码根据任何主机组向mysqld服务器进行身份验证。
注意,目前所有用户都需要将“前端”和“后端“都设置为1,未来版本的ProxySQL将分离前端和后端之间的crendentials。以这种方式,前端将永远不会知道直接连接到后端的凭据,强制所有通过ProxySQL的连接并增加系统的安全性。
mysql_replication_hostgroups表
MySQL [main] 10:18:15 > show create table mysql_replication_hostgroups\G |
定义hostgroup的主从关系。ProxySQL monitor模块会监控hostgroup后端所有servers的read_only变量,如果发现从库的read_only变为0、主库变为1,则认为角色互换了,自动改写mysql_servers表里面hostgroup关系,达到failover效果。
mysql_query_rules查询规则表
MySQL [main] 10:25:22 > show create table mysql_query_rules\G |
rule_id:表主键,自增,规则处理是以rule_id为顺序进行。
首先会检查flagIN=0的规则,以rule_id的顺序;如果没有匹配上,则走这个用户的default_hostgroup。
当匹配一条规则后,会检查flagOUT。
如果不为NULL,并且flagIN!=flagOUT,则进入以flagIN为上一个flagOUT值的新规则链。
如果不为NULL,并且flagIN=flagOUT,则应用这条规则。
如果为NULL,或者apply=1,则结束,应用这条规则。
如果最终没有匹配到,则找到这个用户的default_hostgroup。
以上都是匹配查询的规则,1.4版本可以通过变量mysql-query_processor_regex设置,支持RE2和PCRE,1.4版本开始默认为PCRE。
这是对后端DB的保护机制,相当于阿里云RDS的loose_max_statement_time变量的功能,但不同的是,阿里云这个变量的时间时不包括DML操作出现InnoDB行锁等待的时间,而ProxySQL的这个timeout是计算从发送sql到等待响应的时间。默认mysql-default_query_timeout是10h。
默认值mysql-default_query_delay为0。
log:是否记录查询日志,可以看到log是否记录的对象是根据规则。
要开启日志记录,需要设置变量mysql-eventslog_filename来指定文件名,然后这个log标记为1。但是目前proxysql记录的日志是二进制格式,需要特定的工具才能读取:eventslog_reader_sample。这个工具在源码目录
tools下面。
scheduler调度表
MySQL [main] 10:27:52 > show create table scheduler\G |
id:调度程序作业的唯一标识符。
disk库
MySQL [main] 15:12:14 > show tables from disk;
+------------------------------------+
| tables |
+------------------------------------+
| global_variables |
| mysql_collations |
| mysql_group_replication_hostgroups |
| mysql_query_rules |
| mysql_replication_hostgroups |
| mysql_servers |
| mysql_users |
| proxysql_servers |
| scheduler |
+------------------------------------+
9 rows in set (0.00 sec)
MySQL [main] 15:12:26 >
具体的表介绍和main库一致。
stats库
MySQL [main] 15:12:26 > show tables from stats; |
stats_mysql_commands_counters表
MySQL [stats] 15:15:36 > show create table stats.stats_mysql_commands_counters\G |
- command:已执行的SQL命令的类型,如FLUSH、INSERT、KILL、SELECT FOR UPDATE等。
- Total_Time_us:执行该类型命令的总时间(以毫秒为单位)。
- Total_cnt:执行该类型的命令的总数。
cnt_100us-cnt_INFs:在指定的时间限制内执行的给定类型的命令总数和前一个命令的总数。
##### stats_mysql_connection_pool表
MySQL [stats] 15:15:58 > show create table stats.stats_mysql_connection_pool \G |
hostgroup:后端服务器所属的主机组,单个后端服务器可以属于多个主机组。
Latency_ms:从Monitor报告的当前ping以毫秒为单位的延迟时间。
stats_mysql_global表
MySQL [stats] 15:20:08 > show create table stats.stats_mysql_global\G |
Variable_Name:代表与MySQL相关的代理级别的全局统计
如Client_Connections_aborted:由于无效凭据或max_connections而导致的前端连接数已达到;
如Client_Connections_connected:当前连接的前端连接数。
如Client_Connections_created:到目前为止创建的前端连接数。等等。
Variable_Value:统计所对应的值。
stats_mysql_processlist表
MySQL [stats] 15:24:11 > show create table stats.stats_mysql_processlist\G |
ThreadID:ProxySQL线程的内部ID。
info:正在执行的SQL。
stats_mysql_query_digest表
MySQL [stats] 15:26:43 > show create table stats.stats_mysql_query_digest\G |
hostgroup:发送查询的主机组。值-1表示查询查询缓存。
这对于确定应用程序工作负载中花费的最多时间在哪里是非常有用的,并为改进的地方提供了一个良好的起点。
min_time,max_time - 执行此类查询时期望的持续时间范围。
min_time是到目前为止所看到的最小执行时间,而max_time表示最大执行时间,以微秒为单位。
stats_mysql_query_rules表
MySQL [stats] 15:29:27 > show create table stats.stats_mysql_query_rules\G |
rule_id:路由规则的ID与main.mysql_query_rules的id对应。
monitor库
对后端MySQL的健康检查,由变量mysql-monitor_enabled来确定是否开启Monitor模块。MySQL [stats] 15:35:32 > show tables from monitor;
+------------------------------------+
| tables |
+------------------------------------+
| mysql_server_connect |
| mysql_server_connect_log |
| mysql_server_group_replication_log |
| mysql_server_ping |
| mysql_server_ping_log |
| mysql_server_read_only_log |
| mysql_server_replication_lag_log |
+------------------------------------+
7 rows in set (0.00 sec)
MySQL [stats] 15:35:52 >
mysql_server_connect/mysql_server_connect_log表
MySQL [stats] 15:37:39 > show create table monitor.mysql_server_connect\G |
连接到所有MySQL服务器以检查它们是否可用,该表用来存放检测连接的日志。由变量mysql-monitor_connect_interval来控制其检测的时间间隔,由参数mysql-monitor_connect_timeout控制连接是否超时(默认200毫秒)。
mysql_server_ping/mysql_server_ping_log表
MySQL [stats] 15:39:23 > show create table monitor.mysql_server_ping\G |
使用mysql_ping API ping后端MySQL服务器检查它们是否可用,该表用来存放ping的日志。由变量mysql-monitor_ping_interval控制ping的时间间隔,默认值:10000(毫秒,相当于10秒)。
mysql_server_replication_lag_log表
MySQL [stats] 15:40:53 > show create table monitor.mysql_server_replication_lag_log\G
*************************** 1. row ***************************
table: mysql_server_replication_lag_log
Create Table: CREATE TABLE mysql_server_replication_lag_log (
hostname VARCHAR NOT NULL,
port INT NOT NULL DEFAULT 3306,
time_start_us INT NOT NULL DEFAULT 0,
success_time_us INT DEFAULT 0,
repl_lag INT DEFAULT 0,
error VARCHAR,
PRIMARY KEY (hostname, port, time_start_us))
1 row in set (0.00 sec)
MySQL [stats] 15:41:12 >后端MySQL服务主从延迟的检测。由参数mysql-monitor_replication_lag_interval控制检测间隔时间, 如果复制滞后太大,可以暂时关闭从。由mysql_servers.max_replication_lag列控制。默认值:10000(毫秒,相当于10秒)。
内置参数
global_variables 1.4版本中有95个参数,参数较多,解释请参考文档。
MySQL [main] 11:16:22 > show variables; |
ProxySQL多层配置设计
ProxySQL设计模型介绍
ProxySQL使用多层配置系统,适合满足以下需求:
- 允许自动更新配置,与MySQL兼容管理界面;
- 允许在线修改配置,不用重启ProxySQL;
允许回滚配置;
多层配置系统的实现,如下图:
+-------------------------+ |
RUNTIME代表ProxySQL当前生效的配置,包括global_variables、mysql_servers、mysql_users、mysql_query_rules。无法直接修改这里的配置,必须要从下一层load过来。
MEMORY(main)代表平时在mysql命令行修改的main里的配置,可以认为是SQLite数据库在内存的镜像。可修改以下:
mysql_server 后端服务器列表 |
DISK和CONFIG FILE表示磁盘上SQLite数据库,默认位置在$datadir/proxysql.db,在重新启动过程中,内存中未被保存的配置将丢失。/etc/proxysql.cnf文件只在第一次初始化的时候用到。如要修改端口,还是需要在管理命令行里修改,再save到磁盘。
ProxySQL多层配置修改示例
mysql users
LOAD MYSQL USERS TO RUNTIME / LOAD MYSQL USERS FROM MEMORY |
mysql servers
LOAD MYSQL SERVERS TO RUNTIME 让修改的配置生效 |
mysql query rules
load mysql query rules to run |
mysql variables
load mysql variables to runtime |
admin variables
load admin variables to runtime
save admin variables to memory
load admin variables to memory
save admin variables to disk
load admin variables from config参考
- https://github.com/sysown/proxysql/wiki/Multi-layer-configuration-system
- https://severalnines.com/blog/mysql-load-balancing-proxysql-overview
- http://seanlook.com/2017/04/10/mysql-proxysql-install-config/
ProxySQL读写分离示例
准备
Master:118.190.67.67:3306
Slave :139.196.95.103:3306(192.168.7.50)
ProxySQL:139.196.95.103:3306(192.168.7.50)
版本:percona-server 5.7.18
安装配置
主从安装配置省略。
示例目标
客户端通过访问ProxySQL的ip,实际访问Master和Slave的效果。
添加后端DB服务
100是主库,101是从库,同时主库也处理1/10的读请求,登录ProxySQL管理端设置:
MySQL [(none)] 14:22:06 > insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(100, '118.190.67.67', 3306, 1, 'db0,ReadWrite'),(101, '192.168.7.50', 3306, 9, 'db0,ReadOnly'); |
添加访问用户
登录Master主库设置监控用户和程序用户(由于是测试使用,权限较大,主机允许所有):
MySQL [(none)] 15:51:32 > create user 'monitor'@'%' identified by 'monitor'; |
登录ProxySQL管理端设置:
这里default_hostgroup指定了hostgroup为100的主库,下文会设置SELECT …FOR UPDATE规则到100,SELECT到101,其他所有的SQL到default_hostgroup,也就是主库。
MySQL [(none)] 14:22:15 > INSERT INTO mysql_users (username, password, active, default_hostgroup, max_connections) VALUES ('user0', 'password0', 1, 100, 1000); |
添加复制关系
登录ProxySQL管理端设置:
MySQL [main] 17:32:46 > INSERT INTO mysql_replication_hostgroups VALUES(100,101,'db0'); |
修改全局变量
登录ProxySQL管理端设置:
MySQL [(none)] 14:25:07 > set mysql-query_retries_on_failure=0; |
全局变量生效并保存到磁盘:
登录ProxySQL管理端设置:
MySQL [(none)] 14:25:07 > load mysql users to runtime; |
路由规则
- ProxySQL使用查询规则来确定路由,如果没有规则用于查询,默认会访问hostgroup 0主机组,会报以下错误:
[root@jiessie ~]# mysql -uuser0 -ppassword0 -h 127.0.0.1 -P6033 -e "SELECT 1"
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 9001 (HY000) at line 1: Max connect timeout reached while reaching hostgroup 1 after 2000ms
设置路由规则:
MySQL [(none)] 09:29:14 > use main; |
常用查询
查询连接日志:
MySQL [(none)] 13:45:08 > SELECT * FROM monitor.mysql_server_connect_log ORDER BY time_start_us DESC LIMIT 10; |
查询ping日志:
MySQL [(none)] 13:46:22 > SELECT * FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 10; |
查询后端DB状态
MySQL [(none)] 13:46:55 > SELECT * FROM mysql_servers; |
查询监控状态:
MySQL [(none)] 13:47:56 > SELECT * FROM monitor.mysql_server_read_only_log ORDER BY time_start_us DESC LIMIT 10; |
查询用户信息:
MySQL [(none)] 13:49:28 > SELECT * FROM mysql_users; |
查询连接池:
MySQL [(none)] 13:51:19 > SELECT * FROM stats.stats_mysql_connection_pool; |
查询执行命令统计信息:
MySQL [(none)] 13:51:47 > SELECT * FROM stats_mysql_commands_counters WHERE Total_cnt; |
查询路由规则的详情:
MySQL [(none)] 13:53:05 > SELECT * FROM stats_mysql_query_digest ORDER BY sum_time DESC; |
查询路由规则:
MySQL [(none)] 13:57:12 > SELECT rule_id, match_digest, match_pattern, replace_pattern, cache_ttl, apply FROM mysql_query_rules ORDER BY rule_id;
+---------+--------------+-----------------------+-----------------+-----------+-------+
| rule_id | match_digest | match_pattern | replace_pattern | cache_ttl | apply |
+---------+--------------+-----------------------+-----------------+-----------+-------+
| 10 | NULL | ^SELECT .* FOR UPDATE | NULL | NULL | 0 |
| 11 | NULL | ^SELECT .* | NULL | NULL | 0 |
+---------+--------------+-----------------------+-----------------+-----------+-------+
2 rows in set (0.00 sec)参考:
- https://github.com/sysown/proxysql/wiki/ProxySQL-Configuration#p6033
- http://seanlook.com/2017/04/17/mysql-proxysql-route-rw_split/
- http://severalnines.com/blog/how-proxysql-adds-failover-and-query-control-your-mysql-replication-setup
ProxySQL监控
PMM是Percona推出的一款很好的监控MySQL和MongoDB的开源工具,安装方便,功能丰富,图表美观,同时也支持ProxySQL的监控,故选择PMM作为ProxySQL的监控软件。
这里以ProxySQL服务端(192.168.7.50)为例,作为PMM的客户端,PMM服务器为139.196.99.230,仅演示ProxySQL安装PMM客户端,服务器安装配置省略。
PMM Client安装
[root@jiessie ~]# yum localinstall -y /hwdata/duanwenjie/test/proxysql-1.4.1-1-centos67.x86_64.rpm |
PMM Client配置
[root@jiessie ~]# ifconfig #查看IP地址 |
PMM Server监控展示
PMM Server监控项包括:
总结
ProxySQL是一款很出色的MySQL中间件,在稳定性上、易用性、高性能等方面表现很不错。由于发布的时间较短,功能可能还不太完善,需要多做测试,特别是查询路由和规则方面需要详情的了解,测试。可重点关注。
来源:https://dwj999.github.io/ProxySQL-%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE%E8%AF%A6%E8%A7%A3%E5%8F%8A%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB%E3%80%81%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1.html
评论