1. mysql-proxy实现读写分离的原理
MYSQL读写分离是指让master处理写操作,让slave处理读操作,非常适用于读操作量比较大的场景,可减轻master的压力。
使用mysql-proxy实现mysql的读写分离,mysql-proxy实际上是作为后端mysql主从服务器的代理,它直接接受客户端的请求,对SQL语句进行分析,判断出是读操作还是写操作,然后分发至对应的mysql服务器上。
mysql-proxy是官方提供的mysql中间件产品可以实现负载平衡,读写分离,failover等 MySQL Proxy就是这么一个中间层代理,简单的说,MySQL Proxy就是一个连接池,负责将前台应用的连接请求转发给后台的数据库,并且通过使用lua脚本,可以实现复杂的连接控制和过滤,从而实现读写分离和负载平衡。
对于应用来说,MySQL Proxy是完全透明的,应用则只需要连接到MySQL Proxy的监听端口即可。
当然,这样proxy机器可能成为单点失效,但完全可以使用多个proxy机器做为冗余,在应用服务器的连接池配置中配置到多 个proxy的连接参数即可。
工作原理如图:
2.mysql-proxy实现读写分离的操作
(1)所需环境:
主机ip 角色
172.25.33.1 写库
172.25.33.2 读库
172.25.33.3 proxy代理
在实验开始前,将读库和写库设置为基于gtid的主从异步复制
(2)server3的操作:
<1>下载安装包并解压
[root@server3 ~]# ls
mysql-community-client-5.7.24-1.el7.x86_64.rpm
mysql-community-common-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-server-5.7.24-1.el7.x86_64.rpm
mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz
[root@server3 ~]# tar zxf mysql-proxy-0.8.5-linux-el6-x86-64bit.tar.gz -C /usr/local
<2>停掉server3上的mysqld,因为代理也是3306端口。并且将解压目录重命名
[root@server3 ~]# cd /usr/local
[root@server3 local]# mv mysql-proxy-0.8.5-linux-el6-x86-64bit/ mysql-proxy #重命名,方便一点
<3>创建配置目录和日志目录
[root@server3 local]# cd mysql-proxy/
[root@server3 mysql-proxy]# ls
bin include lib libexec licenses share
[root@server3 mysql-proxy]# mkdir log
[root@server3 mysql-proxy]# ls
bin conf include lib libexec licenses log mysql-proxy.conf share
[root@server3 mysql-proxy]# mkdir conf
[root@server3 mysql-proxy]# cd conf
[root@server3 conf]# vim mysql-proxy.conf
[mysql-proxy]
proxy-address=0.0.0.0:3306
proxy-backend-addresses=172.25.33.1:3306
proxy-read-only-backend-addresses=172.25.33.2:3306
proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
pid-file=/usr/local/mysql-proxy/log/mysql-proxy.pid
plugins=proxy
log-file=/usr/local/mysql-proxy/log/mysql-proxy.log
log-level=debug
keepalive=true
daemon=true
<4>在lua读写分离脚本中,限制最小和最大连接个数 当超出最大连接个数时,就会开启主从复制
[root@server3 mysql-proxy]# vim share/doc/mysql-proxy/rw-splitting.lua
-- connection pool
if not proxy.global.config.rwsplit then
proxy.global.config.rwsplit = {
min_idle_connections = 1,
max_idle_connections = 2,
is_debug = false
}
end
<5>开启mysql-proxy
[root@server3 conf]# chmod 660 /usr/local/mysql-proxy/conf/mysql-proxy.conf
[root@server3 conf]# /usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/conf/mysql-proxy.conf
ps ax
1382 ? S 0:00 /usr/local/mysql-proxy/libexec/mysql-proxy --defaults-fil
1383 ? S 0:00 /usr/local/mysql-proxy/libexec/mysql-proxy --defaults-fil
[root@server3 log]# cat mysql-proxy.log
2019-07-28 13:19:20: (message) chassis-unix-daemon.c:136: [angel] we try to keep PID=1383 alive
2019-07-28 13:19:20: (debug) chassis-unix-daemon.c:157: waiting for 1383
2019-07-28 13:19:20: (debug) chassis-unix-daemon.c:121: we are the child: 1383
2019-07-28 13:19:20: (critical) plugin proxy 0.8.5 started
2019-07-28 13:19:20: (debug) max open file-descriptors = 1024
2019-07-28 13:19:20: (message) proxy listening on port 0.0.0.0:3306
2019-07-28 13:19:20: (message) added read/write backend: 172.25.33.1:3306
2019-07-28 13:19:20: (message) added read-only backend: 172.25.33.2:3306
[root@server3 log]# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1383/mysql-proxy
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 824/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 917/master
tcp6 0 0 :::22 :::* LISTEN 824/sshd
tcp6 0 0 ::1:25 :::* LISTEN 917/master
<6>创建用来读写分离的用户并授权
在server1上:mysql> grant insert,update,select on *.* to wsp@'%' identified by 'Liuyan&123';
Query OK, 0 rows affected, 1 warning (0.38 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.05 sec)
mysql> create database redhat;
Query OK, 1 row affected (0.05 sec)
mysql> use redhat;
Database changed
mysql> create table usertb(
-> username varchar(10) not null,
-> password varchar(15) not null);
Query OK, 0 rows affected (0.57 sec)
mysql> desc usertb;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| username | varchar(10) | NO | | NULL | |
| password | varchar(15) | NO | | NULL | |
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
现在,整个基于mysql-proxy的配置已经完毕,开始测试
<1>首先:真机连三个172.25.33.3,因为只有超过2个才开始读写分离
root@foundation33 ~]# mysql -h 172.25.33.3 -uwsp -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 5.7.24-log MySQL Community Server (GPL)
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| redhat |
| sys |
| westos |
+--------------------+
6 rows in set (0.00 sec)
<2>监控3306端口,看谁访问了3306端口,列出当前系统打开的文件 -i:用来显示符合条件的进程情况
[root@server3 log]# yum install lsof
[root@server3 log]# lsof -i:3306
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysql-pro 1383 root 10u IPv4 27688 0t0 TCP *:mysql (LISTEN)
mysql-pro 1383 root 11u IPv4 31395 0t0 TCP server3:mysql->foundation33.ilt.example.com:34mysql> use redhat;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from usertb;
Empty set (0.00 sec)
886 (ESTABLISHED)
mysql-pro 1383 root 12u IPv4 31396 0t0 TCP server3:39662->server1:mysql (ESTABLISHED)
mysql-pro 1383 root 13u IPv4 31400 0t0 TCP server3:mysql->foundation33.ilt.example.com:34894 (ESTABLISHED)
mysql-pro 1383 root 14u IPv4 31401 0t0 TCP server3:39664->server1:mysql (ESTABLISHED)
mysql-pro 1383 root 15u IPv4 31666 0t0 TCP server3:mysql->foundation33.ilt.example.com:34896 (ESTABLISHED)
mysql-pro 1383 root 16u IPv4 31667 0t0 TCP server3:58558->server2:mysql (ESTABLISHED)
<3>然后在server2上 stop slave,否则会同步到server2上,看不到读写分离的效果;
<4>在真机插入数据:
MySQL [(none)]> use redhat;
MySQL [redhat]> insert into usertb values(‘user1’,‘123’);
<5>在server1中查看,可以看到数据:
mysql> select * from usertb;
+----------+----------+
| username | password |
+----------+----------+
| user1 | 123 |
+----------+----------+
1 row in set (0.00 sec)
<6>在server2中查看,看不到数据,实现了读写分离:
mysql> use redhat;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from usertb;
Empty set (0.00 sec)