mysql基于proxysql 实现读写分离

ProxySQL 读写分离

一、版本介绍

ProxySQL(mysql 中间件):

两个版本:官方版和percona版,percona版是基于官方版基础上修改 C++语言开发,轻量级但性能优异(支持处理千亿级数据),具有中间件所需的绝大多数功能,包括:

  • 多种方式的读/写分离
  • 定制基于用户、基于schema、基于语句的规则对SQL语句进行路由
  • 缓存查询结果
  • 后端节点监控

官方站点:https://proxysql.com/
官方手册:https://github.com/sysown/proxysql/wiki

二、基础信息介绍

2.0 运行原理

​ proxysql代理,会通过一个监控账号连接到主从服务器上,通过判断是否有ready_only选项,来区分哪个是主从服务器,然后把读写服务器分别放在读写组里。读写组的ID和规则都是自定义的。

2.1 ProxySQL组成
  • 服务脚本:/etc/init.d/proxysql
  • 配置文件:/etc/proxysql.cnf
  • 主程序:/usr/bin/proxysql
  • 基于SQLITE的数据库文件:/var/lib/proxysql/
2.2 启动ProxySQL:

systemctl start proxysql

​ 启动后会监听两个默认端口
​ 6032:ProxySQL的管理端口
​ 6033:ProxySQL对外提供服务的端口

2.3 连接ProxySQL

​ 使用mysql客户端连接到ProxySQL的管理接口6032,默认管理员用户和密码都
是admin:

mysql -uadmin -padmin -P6032 -h127.0.0.1
2.4 sqlite数据库说明:

​ proxysql 修改和保存数据都是通过内置的sqlite类型的数据库完成

​ main 是默认的”数据库”名,表里存放后端db实例、用户验证、路由规则等信息。表名以 runtime开头的表示proxysql当前运行的配置内容,不能通过dml语句修改,只能修改对应的不以 runtime 开头的(在内存)里的表,然后 LOAD 使其生效,SAVE 使其存到硬盘以供下次重启加载.

mysql> show databases ;
+-----+---------------+-------------------------------------+
| seq | name          | file                                |
+-----+---------------+-------------------------------------+
| 0   | main          |                                     |
| 2   | disk          | /var/lib/proxysql/proxysql.db       |
| 3   | stats         |                                     |
| 4   | monitor       |                                     |
| 5   | stats_history | /var/lib/proxysql/proxysql_stats.db |
+-----+---------------+-------------------------------------+
5 rows in set (0.00 sec)

数据库:

  • disk 是持久化到硬盘的配置,sqlite数据文件
  • stats 是proxysql运行抓取的统计信息,包括到后端各命令的执行次数、流量、
  • processlist、查询种类汇总/执行时间,等等
  • monitor 库存储 monitor 模块收集的信息,主要是对后端db的健康/延迟检查

其他:

  • 在main和monitor数据库中的表, runtime开头的是运行时的配置,不能修改,
    只能修改非runtime表

  • 修改后必须执行LOAD … TO RUNTIME才能加载到RUNTIME生效

  • 执行save … to disk 才将配置持久化保存到磁盘,即保存在proxysql.db文件中

  • global_variables 有许多变量可以设置,其中就包括监听的端口、管理账号等
    参考: https://github.com/sysown/proxysql/wiki/Global-variables

三、安装

  • centos

    • 基于YUM仓库安装
      cat <<EOF | tee /etc/yum.repos.d/proxysql.repo
      [proxysql_repo]
      name= ProxySQL YUM repository
      baseurl=http://repo.proxysql.com/ProxySQL/proxysql-1.4.x/centos/$releasever
      gpgcheck=1
      gpgkey=http://repo.proxysql.com/ProxySQL/repo_pub_key
      EOF

    • 基于RPM下载安装:https://github.com/sysown/proxysql/releases

  • ubuntu

    step1

       apt-get install -y lsb-release
      	wget -O - 'https://repo.proxysql.com/ProxySQL/repo_pub_key' | apt-key add -
    

    step2

    装1.4系列

    echo deb https://repo.proxysql.com/ProxySQL/proxysql-1.4.x/$(lsb_release -sc)/ ./ \
      | tee /etc/apt/sources.list.d/proxysql.list
    

    装2.0系列

      echo deb https://repo.proxysql.com/ProxySQL/proxysql-2.0.x/$(lsb_release -sc)/ ./ \
      | tee /etc/apt/sources.list.d/proxysql.list
    

    step3

    apt-get update
    
    apt-get install proxysql  或 apt-get install proxysql=version
    

四、使用示例

mark

​ 如图,proxysql 代理服务器,把来自客户数据更改的操作转发给主服务器,查询操作转发给从服务器

1. 搭建主从复制

注意:从服务器一定要配置read_only、 bind-address 0.0.0.0

2. 把所有mysql 服务器添加到mysql_servers 表中

注意:此处的hostgroup_id 不是随便 填写的,与定义的读写组ID相对应,后面定义完读写组ID后,监视账号会自动的把mysql 服务器添加对应的读写组里,(实际上把之前定义过的hostgroup_id,再修改一遍)

特别注意这里两条数据的hostgroup_id是一样的,权重weight也是一样的,前者保证同一个group以便负载均衡,后者权重可以影响负载均衡结果

先连上 proxy 数据库

mysql -uadmin -padmin -P6032 -h127.0.0.1

插入记录

mysql> insert into mysql_servers(hostgroup_id,hostname,port) values(1,'192.168.1.101',3306); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into mysql_servers(hostgroup_id,hostname,port) values(1,'192.168.1.102',3306); 
Query OK, 1 row affected (0.00 sec)

添加到运行中的表,并且持久化保存

mysql> load mysql servers to runtime;
Query OK, 0 rows affected (0.00 sec)

mysql> save mysql servers to disk;
Query OK, 139 rows affected (0.00 sec)
2、创建并且配置监控账号

在master 上创建,slave 会自动复制,不用创建

MariaDB [(none)]> grant replication client on *.* to 'm'@'192.168.%' identified by '123';
Query OK, 0 rows affected (0.00 sec)

在 proxsql 上

set mysql-monitor_username='m';

set mysql-monitor_password='123';

load mysql variables to runtime;

save mysql variables to disk;
3、设置分组信息

旧版版本

​ 需要修改的是main库中的mysql_replication_hostgroups表,该表有3个字段:writer_hostgroup,reader_hostgroup,comment, 指定写组的id为1,读组的id为2

insert into mysql_replication_hostgroups values(1,2,"test");

load mysql servers to runtime;

save mysql servers to disk;

发现已经修改好了之前设置的id

mysql> select * from mysql_servers ;
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname      | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1            | 192.168.1.101 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
| 2            | 192.168.1.102 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
2 rows in set (0.00 sec)

新版本的差异

改成

insert into mysql_replication_hostgroups values(1,2,'read_only','test');

查看当前版本

mysql> select version() ;
+--------------------+
| version()          |
+--------------------+
| 2.0.8-67-g877cab1e |
+--------------------+
1 row in set (0.00 sec)

发现多了一个check_type 字段,检查的类型,默认值是ready_only,用于判断主从的标准

check_type - 执行只读检查时检查的mysql变量,默认情况下为read_only(也可以使用super_read_only)。 对于aws aurora,应使用innodb_read_only

mysql> pragma table_info( mysql_replication_hostgroups);
+-----+------------------+---------+---------+-------------+----+
| cid | name             | type    | notnull | dflt_value  | pk |
+-----+------------------+---------+---------+-------------+----+
| 0   | writer_hostgroup | INT     | 1       | NULL        | 1  |
| 1   | reader_hostgroup | INT     | 1       | NULL        | 0  |
| 2   | check_type       | VARCHAR | 1       | 'read_only' | 0  |
| 3   | comment          | VARCHAR | 1       | ''          | 0  |
+-----+------------------+---------+---------+-------------+----+
4 rows in set (0.00 sec)
4. 配置发送sql 语句的账号

在master 上

MySQL> grant all privelegs on *.* to 's'@'192.168.%' identified by '123';

​ 从上应该刷权限

在ProxySQL配置,

将用户s添加到mysql_users表中, default_hostgroup默认组设置为写组1,当读写分离的路由规则不符合时,会访问默认组的数据库

insert into mysql_users(username,password,default_hostgroup) values('s','123',1);

load mysql users to runtime;

save mysql users to disk;

测试

使用s用户测试是否能路由到默认的1写组实现读、写数据

mysql -us -p123 -P6033 -h127.0.0.1 -e 'select @@server_id' 
mysql -us -p123 -P6033 -h127.0.0.1 -e 'create database testdb' 
mysql -us -p123 testdb -P6033 -h127.0.0.1 -e 'create table t(id int)'
5. 在proxysql上配置路由规则,实现读写分离

​ 插入路由规则:将select语句分离到2的读组,select语句中有一个特殊语句SELECT…FOR UPDATE它会申请写锁,应路由到1的写组

insert into mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply) VALUES(1,1,'^SELECT.*FOR UPDATE$',1,1),(2,1,'^SELECT',2,1);

保存

load mysql query rules to runtime;

save mysql query rules to disk;

注意:

  • 因ProxySQL根据rule_id顺序进行规则匹配,select … for update规则的rule_id必须要小于普通的select规则的rule_id
  • 与规则有关的表:mysql_query_rules和mysql_query_rules_fast_routing,后者是前者的扩展表,1.4.7之后支持
6. 读写分离测试
  • 测试读操作是否路由给2的读组

    mysql -us -p123 -P6033 -h127.0.0.1 -e 'select @@server_id'
    
  • 测试写操作,以事务方式进行测试

    mysql -us -p123 -P6033 -h127.0.0.1 -e 'start transaction;select @@server_id;commit;select @@server_id'
    

    提交是1,提交后是2

  • 查看路由的信息:查询stats库中的stats_mysql_query_digest表

    读写数据,

    root@z3:~# mysql -us -p123  -P6033 -h127.0.0.1 -e 'insert testdb.t values (1)'
    root@z3:~# mysql -us -p123  -P6033 -h127.0.0.1 -e 'select id from testdb.t' 
    

    在proxy看路由

mysql>  SELECT hostgroup hg,sum_time, count_star, digest_text FROM stats_mysql_query_digest ORDER BY sum_time DESC;
+----+----------+------------+----------------------------------+
| hg | sum_time | count_star | digest_text                      |
+----+----------+------------+----------------------------------+
| 1  | 10309    | 1          | create table t(id int)           |
| 2  | 3653     | 3          | select @@server_id               |
| 1  | 3633     | 1          | insert testdb.t values (?)       |

7.查看信息
  • 监控模块的指标保存在monitor库的log表中
  • 查看监控连接是否正常的 (对connect指标的监控):(如果connect_error的结果为NULL则表示正常)
    MySQL> select * from mysql_server_connect_log;
  • 查看监控心跳信息 (对ping指标的监控):
    MySQL> select * from mysql_server_ping_log;
  • 查看read_only和replication_lag的监控日志
    MySQL> select * from mysql_server_read_only_log;
    MySQL> select * from mysql_server_replication_lag_log;
8.修改proxysql默认的监听地址与端口
root@z3:~# vim /etc/proxysql.cnf 

把6033 改成3306 ,才发现端口居然是倒着的,有意思

mysql_variables=
{
        threads=4
        max_connections=2048
        default_query_delay=0
        default_query_timeout=36000000
        have_compress=true
        poll_timeout=2000
#       interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
        interfaces="0.0.0.0:3306"

重启服务即可 systemctl restart proxysql。

呵呵,这是你以为吧

然鹅并无卵用 , 下面是文档原话

#If the database file is found, ProxySQL initializes its in-memory configuration from
# the persisted on-disk database. So, disk configuration gets loaded into memory and# then propagated towards the runtime configuration.
## If the database file is not found and a config file exists, the config file is parsed
# and its content is loaded into the in-memory database, to then be both saved on-disk# database and loaded at runtime.
## IMPORTANT: If a database file is found, the config file is NOT parsed. In this case
# ProxySQL initializes its in-memory configuration from the persisted on-disk# database ONLY. In other words, the configuration found in the proxysql.cnf
# file is only used to initial the on-disk database read on the first startup.

大概意思是说,这个配置文件是针对,初始化新的数据库使用的,即第一次启动proxysql ,如果你已经使用过了数据库,save to disk,下次启动就不会解析这个配置文件,除非找不到这个数据库的硬盘文件。

​ 所以正确的姿势是

mysql> update  global_variables  set variable_value='0.0.0.0:3306' where variable_name='mysql-interfaces';

mysql> save mysql variables to disk;

mysql> proxysql restart ;
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql> select * from global_variables  ;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    5

验证:用另一台服务器测试

root@Z4:~# mysql  -us -p123 -h192.168.1.103  -e 'select @@server_id'
+-------------+
| @@server_id |
+-------------+
|           2 |
+-------------+
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值