五、主从复制案例演示(半同步复制)
实验环境:
Master 服务器:192.168.72.192,mysql5.7
Slave1 服务器:192.168.72.60,mysql5.7
Slave2 服务器:192.168.72.70,mysql5.7
实验操作:
-------1、所有服务器关闭防火墙------ systemctl disable --now firewalld setenforce 0 -------2、主数据库配置--------- vim /etc/my.cnf #在 [mysqld] 区域添加下面内容 ...... plugin-load=rpl_semi_sync_master=semisync_master.so #加载mysql半同步复制的插件 rpl_semi_sync_master_enabled=ON #或者设置为"1",即开启半同步复制功能 rpl-semi-sync-master-timeout=1000 #超时时间为1000ms,即1s systemctl restart mysqld -------3、从数据库配置----------- vim /etc/my.cnf ...... plugin-load=rpl_semi_sync_slave=semisync_slave.so rpl_semi_sync_slave_enabled=ON systemctl restart mysqld -------4、查看半同步是否在运行--------------- #主数据库执行 show status like 'Rpl_semi_sync_master_status'; show variables like 'rpl_semi_sync_master_timeout'; #从数据库执行(此时可能还是OFF状态,需要在下一步重启IO线程后,从库半同步状态才会为ON) show status like 'Rpl_semi_sync_slave_status'; #重启从数据库上的IO线程 STOP SLAVE IO_THREAD; START SLAVE IO_THREAD; #在主库查询半同步状态 show status like '%Rpl_semi%'; 参数说明: Rpl_semi_sync_master_clients #半同步复制客户端的个数 Rpl_semi_sync_master_net_avg_wait_time #平均等待时间(默认毫秒) Rpl_semi_sync_master_net_wait_time #总共等待时间 Rpl_semi_sync_master_net_waits #等待次数 Rpl_semi_sync_master_no_times #关闭半同步复制的次数 Rpl_semi_sync_master_no_tx #表示没有成功接收slave提交的次数 Rpl_semi_sync_master_status #表示当前是异步模式还是半同步模式,on为半同步 Rpl_semi_sync_master_timefunc_failures #调用时间函数失败的次数 Rpl_semi_sync_master_tx_avg_wait_time #事物的平均传输时间 Rpl_semi_sync_master_tx_wait_time #事物的总共传输时间 Rpl_semi_sync_master_tx_waits #事物等待次数 Rpl_semi_sync_master_wait_pos_backtraverse #可以理解为"后来的先到了,而先来的还没有到的次数" Rpl_semi_sync_master_wait_sessions #当前有多少个session因为slave的回复而造成等待 Rpl_semi_sync_master_yes_tx #成功接受到slave事物回复的次数 当半同步复制发生超时(由rpl_semi_sync_master_timeout参数控制,默认为10000ms,即10s),会暂时关闭半同步复制,转而使用异步复制,也就是会自动降为异步工作。 当 master dump 线程发送完一个事务的所有事件之后,如果在 rpl_semi_sync_master_timeout 内,收到了从库的响应, 则主从又重新恢复为半同步复制。 复制代码
注意:
1)在一主多从的架构中,如果要开启半同步复制,并不要求所有的从都是半同步复制。
2)MySQL 5.7极大的提升了半同步复制的性能。
- 5.6 版本的半同步复制,dump thread 承担了两份不同且又十分频繁的任务:传送binlog 给 slave ,还需要等待 slave 反馈信息,而且这两个任务是串行的,dump thread 必须等待 slave 返回之后才会传送下一个 events 事务。dump thread 已然成为整个半同步提高性能的瓶颈。在高并发业务场景下,这样的机制会影响数据库整体的系统吞吐量(TPS)。
- 5.7 版本的半同步复制中,独立出一个 ack collector thread ,专门用于接收 slave 的反馈信息。这样 master 上有两个线程独立工作,可以同时发送 binlog 到 slave ,和接收 slave 的反馈。
半同步复制什么情况下会降为异步复制?什么时候又会恢复同步复制?
- 当半同步复制发生超时(由rpl_semi_sync_master_timeout 参数控制,默认为10000ms, 即10s),会暂时关闭半同步复制,转而使用异步复制,也就是会自动降为异步工作。
- 当malster dump 线程发送完一个事务的所有事件之后,如果在rpl_ semi_sync_master_ timeout 内,收到了从库的响应,则主从又重新恢复为半同步复制。
六、读写分离概念
6.1 MySQL读写分离原理
- 读写分离就是只在主服务器上写,只在从服务器上读。
- 基本的原理是让主数据库处理事务性操作,而从数据库处理select查询。
- 数据库复制被用来把主数据库上事务性操作导致的变更,同步到集群中的从数据库。
6.2 目前较为常见的MysQL读写分离分为以下两种
1)基于程序代码内部实现
在代码中根据select、insert进行路由分类,这类方法也是目前生产环境应用最广泛的。
优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。
2)基于中间代理层实现
代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序。
(1)MySQL-Proxy。MySQL-Proxy为MysQL开源项目,通过其自带的1ua脚本进行sQL判断。
(2)Atlas。是由奇虎360的Web平台部基础架构团队开发维护的一个基于MysQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用atlas运行的mysql业务,每天承载的读写请求数达几干保条。支持事物以及存储过程。
(3)Amoeba。由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。
(4)Mycat。是一款流行的基于Java语言编写的数据库中间件,是一个实现了MySq1协议的服务器,其核心功能是分库分表。配合数据库的主从模式还可以实现读写分离。
由于使用MysQLProxy需要写大量的ua脚本,这些Lua并不是现成的,而是需要自己去写。这对于并不熟悉MysQLProxy 内置变量和MySQL Protocol的人来说是非常困难的。
Amoeba是一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层。
七、读写分离案例(使用Amoeba)
实验环境:
Master 服务器:192.168.72.192,mysql5.7,centos7-2
Slave1 服务器:192.168.72.60,mysql5.7,centos7-6
Slave2 服务器:192.168.72.70,mysql5.7,centos7-7
Amoeba 服务器:192.168.72.30,jdk1.6、Amoeba centos7-3
客户端:192.168.72.40, mysql5.7,centos7-4
7.1 Amoeba服务器配置 192.168.72.30
1)安装 Java 环境
#因为 Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。 #先将jdk的二进制文件上传到/opt/目录下,之后复制到/usr/local/目录下 [root@Amo ~]# cd /opt/ [root@Amo opt]# cp jdk-6u14-linux-x64.bin /usr/local/ [root@Amo opt]# cd /usr/local/ [root@Amo local]# chmod +x jdk-6u14-linux-x64.bin #为二进制文件增加执行权限 [root@Amo local]# ./jdk-6u14-linux-x64.bin ##按yes,按enter [root@Amo local]# mv jdk1.6.0_14/ /usr/local/jdk1.6 #将jdk目录重命名 #添加环境变量 [root@Amo local]# vim /etc/profile export JAVA_HOME=/usr/local/jdk1.6 export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH export AMOEBA_HOME=/usr/local/amoeba export PATH=$PATH:$AMOEBA_HOME/bin [root@Amo local]# source /etc/profile #刷新文件,使立即生效 [root@Amo local]# java -version #查看jdk版本 复制代码
2)安装 Amoeba软件
-------1、安装 Amoeba软件--------- #创建Amoeba的解压目录 [root@Amo ~]# mkdir /usr/local/amoeba/ #将Amoeba安装包上传到/opt/目录,解压安装包 [root@Amo opt]# cd /opt/ [root@Amo opt]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/ #增加目录权限 [root@Amo opt]# chmod -R 755 /usr/local/amoeba/ #开启Amoeba [root@Amo opt]# /usr/local/amoeba/bin/amoeba #如显示amoeba start|stop说明安装成功 -------2、配置 Amoeba读写分离,两个 Slave 读负载均衡---------- #先在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问。注意:这里授权的用户名和密码,会在下一步写入数据库配置文件。 grant all on *.* to yuji@'192.168.72.%' identified by '123123'; #再回到amoeba服务器配置amoeba服务: [root@Amo opt]# cd /usr/local/amoeba/conf/ #备份配置文件,修改amoeba配置文件 [root@Amo conf]# cp amoeba.xml amoeba.xml.bak [root@Amo conf]# vim amoeba.xml --30行-- <property name="user">amoeba</property> #30行和32行,授权客户端用于登录amoeba的账号和密码 --32行-- <property name="password">123456</property> --115行-- <property name="defaultPool">master</property> #设置默认服务器池 --117-去掉注释- <property name="writePool">master</property> #定义写的服务器池名称 <property name="readPool">slaves</property> #定义读的服务器池名称 #备份数据库配置文件,之后修改数据库配置文件dbServers.xml [root@Amo conf]# cp dbServers.xml dbServers.xml.bak [root@Amo conf]# vim dbServers.xml --23行--注释掉 作用:默认进入test库,注释掉以防mysql中没有test库时,会报错 <!-- <property name="schema">test</property> --> ##26-30行,此用户就是之前在3台主从服务器上授权的用户,授权amoeba服务器用来登录mysql数据库的用户和密码。 --26行--修改 <property name="user">yuji</property> --28-30行--去掉注释 <property name="password">123123</property> --45行--修改,设置主服务器的名称master和地址 <dbServer name="master" parent="abstractServer"> --48行--修改,设置主服务器的地址 <property name="ipAddress">192.168.72.192</property> --52行--修改,设置从服务器1的名称slave1 <dbServer name="slave1" parent="abstractServer"> --55行--修改,设置从服务器1的地址 <property name="ipAddress">192.168.72.60</property> --58行--复制上面6行粘贴,设置从服务器2的名称slave2和地址 <dbServer name="slave2" parent="abstractServer"> <property name="ipAddress">192.168.72.70</property> --65行--修改 <dbServer name="slaves" virtual="true"> --71行--修改 <property name="poolNames">slave1,slave2</property> [root@Amo conf]# /usr/local/amoeba/bin/amoeba start & #后台启动Amoeba软件,按ctrl+c 返回 [root@Amo conf]# netstat -anpt | grep java #查看8066端口是否开启,默认端口为TCP 8066 复制代码
先在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问:
再回到amoeba服务器配置amoeba服务:
修改amoeba的配置文件amoeba.xml