一、为什么要进行读写分离
为了确保数据库产品的稳定性,很多数据库拥有双机热备功能。也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器;第二台数据库服务器,主要进行读的操作。
对于很多大型网站(pv值百万、千万)来说,在所处理的业务中,其中有70%的业务是查询(select)相关的业务操作
(新闻网站,插入一条新闻,查询操作)
剩下的则是写(insert、update、delete,只要能对MySQL的数据造成更改的操作都叫写操作)操作
在使用负载均衡集群之后,可以很大程度的提升网站的整体性能,但是最终的数据处理的压力还是会落到MySQL数据库上
所有很有必要使用一些技术来提升MySQL的负载能力。(读写分离)
写专门交给写服务器处理(一般网站来说写是比较少的 读写比 4:1) 那么需要把读的任务分配多台服务器来完成的架构,就叫做读写分离
二、读写分离的实现方式
(1)php程序上自己做逻辑判断,写php代码的时候,自己在程序上做逻辑判读写匹配。select,insert、update、delete做正则匹配,根据结果选择写服务器(主服务器)。如果是select操作则选择读服务器(从服务器器) mysql_connect(‘读写的区分’)
(2)MySQL- Proxy是实现"读写分离(Read/Write Splitting)"的一个软件(MySQL官方提供 ,也叫中间件),基本的原理是让主数据库处理写操作(insert、update、delete),而从数据库处理查询操作(select)。而数据库的一致性则通过主从复制来实现。所以说主从复制是读写分离的基础。
注意:MySQL-proxy 它能实现读写语句的区分主要依靠的是内部一个lua脚本(能实现读写语句的判断)
注意:如果只在主服务器(写服务器)上完成数据的写操作话;这个时候从服务器上没有执行写操作,是没有数据的
这个时候需要使用另外一个技术来实现主从服务器的数据一致性,这个技术叫做 主从复制技术, 所以说主从复制是读写分离的基础
读写分离(MySQL- Proxy)是指让master处理写操作,让slave处理读操作,非常适用于读操作量比较大的场景,可减轻master的压力
使用mysql-proxy实现mysql的读写分离,mysql-proxy实际上是作为后端mysql主从服务器的代理,它直接接受客户端的请求
对SQL语句进行分析,判断出是读操作还是写操作,然后分发至对应的mysql服务器上
因为数据库的写操作相对读操作是比较耗时的,所以数据库的读写分离,解决的是数据库的写入,影响了查询的效率
先把环境还原到基于gtid的主从复制模式
server1上
[root@server1 ~]# systemctl status mysqld.service
[root@server1 ~]# systemctl start mysqld.service
[root@server1 ~]# cat /var/log/mysqld.log 查看临时密码
[root@server1 ~]# vim /etc/my.cnf
[root@server1 ~]# systemctl restart mysqld
server2上
前面的安装启动与server1一样
[root@server2 mysql]# vim /etc/my.cnf编辑配置文件
测试
在server1创建数据库
在server2上查看
mysql> show slave status\G;
主机名 IP 角色 服务
server1 172.25.254..1 master mysqld
server2 172.25.254.2 slave mysqld
server3 172.25.254.3 代理端 mysql-proxy
实验环境已经搭配完成(关于gtid的主从复制)
server1做读、写库
server2做读库
server3做proxy代理
并且两个库(server1和server2)要实现读写分离,但是还要实现数据同步,基于gtid的异步复制(主从复制
接下来配置server3代理端(mysql-proxy)
https://downloads.mysql.com/archives/proxy/ 下载第一个
没有log目录需要创建
[root@server3 mysql-proxy]# mkdir log 创建目录日志存储
[root@server3 mysql-proxy]# ls
bin conf include lib libexec licenses log mysql-proxy.conf share
前面配置文件位置不对这里移动到conf下
[root@server3 mysql-proxy]# mv mysql-proxy.conf conf/
[root@server3 mysql-proxy]# ls
bin conf include lib libexec licenses log share
进入lua脚本位置
设定读写分离启动参数
[root@server3 mysql-proxy]# cat log/mysql-proxy.log
2020-05-17 03:31:59: (message) chassis-unix-daemon.c:136: [angel] we try to keep PID=8042 alive
2020-05-17 03:31:59: (debug) chassis-unix-daemon.c:157: waiting for 8042
2020-05-17 03:31:59: (debug) chassis-unix-daemon.c:121: we are the child: 8042
2020-05-17 03:31:59: (critical) plugin proxy 0.8.5 started
2020-05-17 03:31:59: (debug) max open file-descriptors = 1024
2020-05-17 03:31:59: (message) proxy listening on port 0.0.0.0:3306
2020-05-17 03:31:59: (message) added read/write backend: 172.25.254.1:3306读写库
2020-05-17 03:31:59: (message) added read-only backend: 172.25.254.2:3306只读库
测试读写分离
数据库在初始化 时限制了其他用户远程登录,需要在server1上创建一个用户并且下方远程登录查看权限
在server1上
物理机远程登录查看
server3上查看读写分离
[root@server3 ~]# lsof -i:3306 可以看到当前访问server3数据库指向到server1上
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysql-pro 8042 root 10u IPv4 52223 0t0 TCP *:mysql (LISTEN)
mysql-pro 8042 root 11u IPv4 54984 0t0 TCP server3:mysql->client:35864 (ESTABLISHED)
mysql-pro 8042 root 12u IPv4 54985 0t0 TCP server3:36050->server1:mysql (ESTABLISHED)
由于设置的lua脚本里面参数当超过两次连接后读写分离才会启动
再在物理机上连接登录三次查看读写分离状态
此时再去server3查看读写分离已经启动
证明读写分离启动后server1只有可读可写 server2只能读
物理机上创建用户
当前状态下读写分离不明显,因为我们开起了基于gtid的主从复制,在server1上写的数据会同步到server2上,为了效果更佳明显关闭server2上的salve节点,这样读写分离开启后在server1上的写的数据在查看是只能在server1这台主机上。
实验过程
在关闭server2slave节点后可以的得出
对于server1实现了读写,
对于server2只实现了读没有写权限
当访问数据库的真机(用户)数量很多的时候,数据库的代理server3就会把后端的数据库实现读写分离
真机在创建用户实际操作的是server1,对于server2没有控制当用命令去查看实际去看的是server2.
server1是读写的数据库
server2是读的数据库
打开slave都可以看到数据
当server1和server2满足gtid的异步复制的时候,真机往数据库写入的东西其实是写入了server1,并没有写入server2,server2上面的数据是复制过去的
所以server1和server2、真机上面都能查到刚刚写进去的数据,其实真机查的是server2(读)
当关闭server2的slave节点的时候,真机往数据库写入的数据只写进了server1,没有写进去server2,server2也不会去复制
因为server1可以查看到数据,server2和真机上面都查不到刚刚写进去的数据,此时的真机读的是server2