基于Maxscale中间件实现Mysql读写分离实战

环境介绍:

 CentOS 7.5

 Mysql 5.7.29

 Mysql主服务器:192.168.2.128

 Mysql从服务器:192.168.2.129

 Mysql代理服务器:192.168.2.130

 客户端服务器:192.168.2.132

读写分离概述:

1、什么是读写分离?

 读写分离的基本原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。一般来说都是通过 主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力这样的方案来进行部署与实施的。

2、为什么要读写分离?

 因为数据库的“写”操作是比较耗时的,但是数据库的“读”操作耗时非常短,所以读写分离,解决的是数据库的写入影响了查询的效率(即读操作比写操作多的场景)。

3、什么时候读写分离?

 数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用,利用数据库主从同步,可以减少数据库压力,提高性能。

4、主从复制与读写分离:

 在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的。无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。

5.读写分离的好处:

 1)分摊服务器压力, 减轻主服务器的工作压力,提高机器的系统处理效率。 2)增加冗余,提高服务可用性,当一台数据库服务器宕机后可以调整另外一台从库以最快速度恢复服务。

 读写分离适用于读远比写多的场景,如果有一台服务器,当select很多时,update和delete会被这些select访问中的数据堵塞,等待select结束,并发性能并不高,而主从只负责各自的写和读,极大程度的缓解X锁和S锁争用。

共享锁[S锁]   -->读锁 排他锁[X锁]   -->写锁 读锁是共享的,或者说是相互不阻塞的。 写锁是排他的,一个写锁会阻塞其他的写锁和读锁。

6.实现Mysql读写分离常见的2种方式:

1)基于程序代码内部实现

 在代码中根据select 、insert进行路由分类,这类方法也是目前生产环境下应用最广泛的。优点是性能较好,因为程序在代码中实现,不需要增加额外的硬件开支,缺点是需要开发人员来实现,运维人员无从下手。

2) 基于中间件(代理层)实现

 代理一般介于应用服务器和数据库服务器之间,代理数据库服务器接收到应用服务器的请求后根据判断后转发到后端数据库。如:Mycat、Mysql-proxy、Maxscale...

构建思路:

 1.配置Mysql主从同步

 这里就不讲述Mysql主从同步的配置了,上面一篇文章里面讲得很详细,大家可以去看一下。

 2.部署Maxscale服务

 Maxscale下载:https://downloads.mariadb.com/MaxScale/

1.下载并安装Maxscale服务

[root@test3 ~]# wget  [root@test3 ~]# ll maxscale-2.1.2-1.rhel.7.x86_64.rpm -rw-r--r-- 1 root root  3月  31 2017 maxscale-2.1.2-1.rhel.7.x86_64.rpm [root@test3 ~]# yum -y install maxscale-2.1.2-1.rhel.7.x86_64.rpm ... 已安装:   maxscale.x86_64 0:2.1.2-1 作为依赖被安装:   gnutls.x86_64 0:3.3.29-9.el7_6             nettle.x86_64 0:2.7.1-8.el7             trousers.x86_64 0:0.3.14-2.el7 完毕! [root@test3 ~]# max (连续按Tab两次)    //maxscale服务的管理命令 maxadmin        maxavrocheck    maxbinlogcheck  maxkeys         maxpasswd [root@test3 ~]# ll /etc/maxscale.cnf      //配置文件 -rw-r--r-- 1 root root 1560 6月   9 16:40 /etc/maxscale.cnf -----下面是备份maxscale服务的配置文件----- [root@test3 ~]# mkdir maxscale [root@test3 ~]# cp /etc/maxscale.cnf /root/maxscale/ [root@test3 ~]# ll /root/maxscale/ 总用量 4 -rw-r--r-- 1 root root 1560 6月   9 16:44 maxscale.cnf

2.修改Maxscale配置文件

[root@test3 ~]# vim /etc/maxscale.cnf [maxscale] threads=auto     //线程数,auto表示自动根据cpu的性能创建多少个线程 ... [server1]       //定义数据库服务器的主机名 type=server address=192.168.2.128     //master(主库)主机的ip地址 port=3306 protocol=MySQLBackend ... [server2]      //定义数据库服务器的主机名 type=server address=192.168.2.129     //slave(从库)主机ip地址 port=3306 protocol=MySQLBackend ... [MySQL Monitor]        //定义要监视的服务器及监控的用户 type=monitor module=mysqlmon servers=server1,server2     /主、从数据库的主机名 user=maxscalemon       //监控用户名 password=123q...A     //监控用户密码 monitor_interval=10000     //监控的时间间隔,单位为毫秒 ... #[Read-Only-Service]   //读负载均衡模块,由于读写分离模块也能实现读负载均衡,因此注释掉该模块 #type=service #router=readconnroute #servers=server1 #user=myuser #password=mypwd #router_options=slave ... [Read-Write-Service]     //定义读写分离服务及路由用户 type=service   router=readwritesplit servers=server1,server2     //主、从数据库的主机名 user=maxscalerouter       //路由用户名 password=123q...A       //路由用户密码 max_slave_connections=100%     //多少比例的从服务器被使用,默认就是所有从服务器都提供读服务 ... [MaxAdmin Service]      //定义管理服务 type=service router=cli #[Read-Only-Listener]      //注释该模块 #type=listener #service=Read-Only-Service #protocol=MariaDBClient #port=4008 [Read-Write-Listener]        //定义读写分离服务的端口号 type=listener service=Read-Write-Service protocol=MySQLClient port=4006 [MaxAdmin Listener]        //定义管理服务的端口号 type=listener service=MaxAdmin Service protocol=maxscaled socket=default port=4016

3.在主数据库上创建授权用户

[root@localhost ~]# mysql -uroot -p123q...A ... mysql> grant replication slave,replication client on *.* to maxscalemon@"%" identified by "123q...A";     //创建监控用户授权 mysql> grant select on mysql.* to maxscalerouter@"%" identified by "123q...A";     //创建路由用户授权 mysql> select user,host from mysql.user where user like "maxscale%"; +----------------+------+ | user           | host | +----------------+------+ | maxscalemon    | %    | | maxscalerouter | %    | +----------------+------+

4.在从数据库上查看主库上授权的用户是否同步

[root@test2 ~]# mysql -uroot -p123q...A ... mysql> select user,host from mysql.user where user like "maxscale%"; +----------------+------+ | user           | host | +----------------+------+ | maxscalemon    | %    | | maxscalerouter | %    | +----------------+------+

5.在代理服务器上启动Maxscale服务

[root@test3 ~]# maxscale -f /etc/maxscale.cnf     //启动maxscale服务 [root@test3 ~]# ss -antulp | grep maxscale tcp    LISTEN     0      128      :::4006                 :::*                   users:(("maxscale",pid=2732,fd=11))         //查询读写分离端口号4006是否启用 tcp    LISTEN     0      128      :::4016                 :::*                   users:(("maxscale",pid=2732,fd=12))         //查询管理服务端口号4016是否启用

测试配置:

1.在代理服务器本机访问Maxscale管理服务

 -maxadmin -uadmin -pmariadb -P管理服务端口号

[root@test3 ~]# maxadmin -uadmin -pmariadb -P4016 MaxScale> list servers      //显示监控信息(集群状态) Servers. -------------------+-----------------+-------+-------------+-------------------- Server             | Address         | Port  | Connections | Status -------------------+-----------------+-------+-------------+-------------------- server1            | 192.168.2.128   |  3306 |           0 | Master, Running server2            | 192.168.2.129   |  3306 |           0 | Slave, Running -------------------+-----------------+-------+-------------+--------------------   //详细信息server1为主服务器,server2为从服务器,running为开启状态,ip以及主机端口

2.在主服务器上新增数据及授权连接用户

[root@localhost ~]# mysql -uroot -p123q...A mysql> create database gamedb;     //创建gamedb库 mysql> create table gamedb.a(id int);     //在gamedb库创建名为a的表 mysql> show databases; +--------------------+ | Database           | +--------------------+ | information_schema | | db1                | | gamedb             | | mysql              | | performance_schema | | sys                | | test               | | zabbix             | +--------------------+ mysql> use gamedb; mysql> show tables; +------------------+ | Tables_in_gamedb | +------------------+ | a                | +------------------+ mysql> grant select,insert on gamedb.* to tom66@"%" identified by "123q...A";            //授权连接用户tom66,权限为select、insert mysql> select user,host from mysql.user where user like "tom66"; +-------+------+ | user  | host | +-------+------+ | tom66 | %    | +-------+------+

3.客户端132连接代理服务器130访问数据

 -mysql -h服务器地址 -P读写分离服务端口号 -u用户名 -p密码

[root@VOS3000 ~]# mysql -P4006 -h192.168.2.130 -utom66 -p123q...A ... mysql> show databases; +--------------------+ | Database           | +--------------------+ | information_schema | | gamedb             | +--------------------+ mysql> use gamedb; mysql> show tables; +------------------+ | Tables_in_gamedb | +------------------+ | a                | +------------------+

验证代理服务器读写分离功能:

 -在从数据库服务器上添加新数据,主数据库服务器上并不会同步这些数据,客户端访问代理服务器访问数据时能看到从服务新添加的数据,说明读数据时是读取的从数据库服务器上的数据。(验证读写分离中的从“读”)

 -在代理服务器上添加新数据,到主数据库服务器上查看新数据写入情况,说明写数据时是在主服务上写。(验证读写分离中的主“写”)

1.在从数据库服务器上添加新数据

 在从服务器上新增数据,并不会同步到主数据库服务器上。

[root@test2 ~]# mysql -uroot -p123q...A ... mysql> show databases; +--------------------+ | Database           | +--------------------+ | information_schema | | db1                | | gamedb             | | mysql              | | performance_schema | | sys                | | test               | | zabbix             | +--------------------+ mysql> use gamedb; mysql> show tables; +------------------+ | Tables_in_gamedb | +------------------+ | a                | +------------------+ mysql> insert into gamedb.a values(55); mysql> select * from gamedb.a; +------+ | id   | +------+ |   55 | +------+

2.在主数据库服务器上查看数据

[root@localhost ~]# mysql -uroot -p123q...A ... mysql> select * from gamedb.a; Empty set (0.00 sec)       //没有数据

 可以看到主数据库服务器上并没有新增数据。

3.客户端访问代理服务器查看数据

[root@VOS3000 ~]# mysql -P4006 -h192.168.2.130 -utom66 -p123q...A ... mysql> select * from gamedb.a; +------+ | id   | +------+ |   55 | +------+

 可以看到客户端通过代理服务器访问到了之前在从数据库服务器上新增的数据,所以说明代理服务器读数据是读取的从服务器上的数据。

4.客户端连接代理服务器新增数据

[root@VOS3000 ~]# mysql -P4006 -h192.168.2.130 -utom66 -p123q...A ... mysql> select * from gamedb.a;     //读取到从服务器上之前新增的数据 +------+ | id   | +------+ |   55 | +------+ mysql> insert into gamedb.a values(88); mysql> insert into gamedb.a values(100); mysql> select * from gamedb.a;   //查看新增的数据 +------+ | id   | +------+ |   55 | |   88 | |  100 | +------+

5.主数据库服务器查看客户端通过代理服务新增的数据

[root@localhost ~]# mysql -uroot -p123q...A ... mysql> select * from gamedb.a; +------+ | id   | +------+ |   88 | |  100 | +------+

 可以看到刚才通过客户端连接代理服务器新增的两条数据全部都写入到了主数据库服务器中并同步到从服务器上。

6.从数据库服务器上查看数据同步情况

[root@test2 ~]# mysql -uroot -p123q...A ... mysql> select * from gamedb.a; +------+ | id   | +------+ |   55 |       |   88 | |  100 | +------+

总结:

 上面的实验说明代理服务器实现了读写分离功能。

   -写数据时,代理服务器会在主数据库服务器上写。(在主数据库服务器上写入的数据会同步到从数据库服务器上)

   -读数据时,代理服务器会在从数据库服务器上读。

如果你觉得这篇文章还不错,就请动动你的发财手为本文点赞-评论-转发吧,因为这将是我持续输出更多优质文章的最强动力,谢谢!