MySQL(十)主从复制与读写分离

目录

一、主从复制

1、原理

2、mysql支持的复制类型

3、主从复制的工作过程

4、MySQL主从复制延迟

二、MySQL 主从复制架构搭建

1、前期准备

2、文件配置

3、验证主从复制

三、读写分离介绍

1、基本概念

2、实现方式

四、MySQL 读写分离架构搭建

1、前期准备

2、配置 amoeba 读写分离,之前两个 slave做读负载均衡

3、客户端测试读写分离

4、关闭 slave 功能后在主从服务器插入数据

5、关闭 slave 功能后,客户端服务器写入数据

6、从服务器开启 slave 服务

7、客户端服务器再次插入数据

总结


一、主从复制

        MySQL 的主从复制和 MySQL 的读写分离两者有着紧密联系,首先要部署主从复制,只有主

从复制完成了,才能在此基础上进行数据的读写分离。

1、原理

主从复制的核心:2个日志、3个线程

master 线程:bin log 二进制日志、dump 线程

master 上的 dump 线程会监控 bin log 二进制日志的更新,若有更新会通知 slave的 I/O 线程

slave:relay log 中继日志、I/O 线程、SQL 线程

线程1:

slave上的 I/O 线程会向 master 申请同步 bin log 二进制日志的更新内容,slave的 I/O 线程把更新

内容写入自己的中继日志

线程2:

slave 的 SQL 线程把日志中的更新语句同步执行到内容,以达到和 master 数据库趋于一致

2、mysql支持的复制类型

        基于语句的复制:在主服务器上执行的 SQL 语句,在从服务器上执行同样的语句;MySQL

默认采用基于语句的复制,效率比较高。

        基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍。

        混合类型的复制:默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用

基于行的复制。

3、主从复制的工作过程

(1)Master节点将数据的改变记录成二进制日志(bin log),当Master上的数据发生改变时,则

将其改变写入二进制日志中。

(2)Slave节点会在一定时间间隔内对Master的二进制日志进行探测其是否发生改变,如果发生改

变,则开始一个I/O线程请求 Master的二进制事件。

(3)同时Master节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至

Slave节点本地的中继日志(Relay log)中,Slave节点将启动SQL线程从中继日志中读取二进制

日志,在本地重放,即解析成 sql 语句逐一执行,使得其数据和 Master节点的保持一致,最后I/O

线程和SQL线程将进入睡眠状态,等待下一次被唤醒。

注:

●中继日志通常会位于 OS 缓存中,所以中继日志的开销很小。

●复制过程②有一个很重要的限制,即复制在 Slave上是串行化的,也就是说 Master上的并行更新

操作不能在 Slave上并行操作。

4、MySQL主从复制延迟

①、master服务器高并发,形成大量事务

②、网络延迟

③、主从硬件设备导致:cpu主频、内存io、硬盘io

④、本来就不是同步复制、而是异步复制

        从库优化Mysql参数。比如增大innodb_buffer_pool_size,让更多操作在Mysql内存中完成,

减少磁盘操作。

        从库使用高性能主机。包括cpu强悍、内存加大。避免使用虚拟云主机,使用物理主机,这样

提升了i/o方面性。

从库使用SSD磁盘

网络优化,避免跨机房实现同步

二、MySQL 主从复制架构搭建

1、前期准备

①、确认各主机名及IP地址,以下均在CentOS 7环境下配置。

主机名

IP地址

主要软件

Master(主)

192.168.110.128

mysql-5.7

Slave1(从)

192.168.110.129

mysql-5.7

Slave2(从)

192.168.110.130

mysql-5.7

Amoeba(中继)

192.168.110.131

jdk1.6、Amoeba

client(客户端)

192.168.110.132

mysql-5.7


②、环境确认,关闭防火墙与安全增强系统

systemctl stop firewalld 
systemctl disable firewalld
setenforce 0

③、主从服务器时间同步

##############master#############
[root@master ~]# yum install -y ntp
[root@master ~]# vim /etc/ntp.conf    #添加下面内容
……
server 127.127.80.0            #设置本地是时钟源,注意修改自己的网段
fudge 127.127.80.0 stratum 8    #设置时间层级为 8(限制在 15 内)
……
[root@slave2 ~]# systemctl start ntpd
##############selave1和selave2#############
[root@slave1 ~]# yum install -y ntp ntpdate
[root@slave1 ~]# systemctl start ntpd
[root@slave1 ~]# /usr/sbin/ntpdate 192.168.110.128  #设置与主服务器时间同步
2 Nov 00:28:31 ntpdate[18122]: the NTP socket is in use, exiting  
[root@slave1 ~]# crontab -e     #设置计划任务
*/30 * * * * /usr/sbin/ntpdate 192.168.110.128
#两台从服务器时间同步步骤一致

2、文件配置

①、主服务器的 mysql 配置

[root@master ~]# vim /etc/my.cnf
……
[mysqld]
server-id = 1         #定义 server-id,每台主机不可相同
log-bin=master-bin   #主服务器开启二进制日志
binlog_format = MIXED   	#本次使用 MIXED 模式
log-slave-updates=true    #允许从服务器更新二进制日志
[root@master ~]# systemctl restart mysqld.service  #重启服务

[root@master ~]# mysql -uroot -p    #进入mysql环境
Enter password:
#给从服务器授权
mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.110.%' IDENTIFIED BY '1234556';
mysql> flush privileges;
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 |      154 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

mysql>     #File 列显示日志名,Position 列显示偏移量

②、从服务器的 mysql 配置

##############selave1 #############
[root@slave1 ~]# vim /etc/my.cnf  #添加如下内容
……
server-id = 2								#注意 id 与其他主机都不能相同
relay-log=relay-log-bin						#开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index		#定义中继日志文件的位置和名称
relay_log_recovery = 1                  	#选配项
#当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 
relay-log,并且重新从 master 上获取日志,这样就保证了relay-log 的完整性。默认情况下该功能是关闭
的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启。
#配置同步,注意 master_log_file 和 master_log_pos 的值要与 Master 查询的一致
mysql> CHANGE master to master_host='192.168.110.128',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;
mysql> start slave;							#启动同步,如有报错执行 reset slave;

############## selave2#############
[root@slave1 ~]# vim /etc/my.cnf  #添加如下内容
……
server-id = 3								
relay-log=relay-log-bin						
relay-log-index=slave-relay-bin.index		
relay_log_recovery = 1                  
mysql> CHANGE master to master_host='192.168.110.128',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;
mysql> start slave;							
############## 查看 Slave 状态 #############
mysql> show slave status\G;
#确保 IO 和 SQL 线程都是 Yes,代表同步正常。

注意:一般 Slave_IO_Running: No 的可能性

①、网络不通

②、my.cnf配置有问题

③、密码、file文件名、pos偏移量不对

④、防火墙没有关闭

3、验证主从复制

 

三、读写分离介绍

1、基本概念

        在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求

的。无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,通过

主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。有点类似于rsync,

但是不同的是rsync是对磁盘文件做备份,而mysql主从复制是对数据库中的数据、语句做备份。

①、读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、

DELETE),即只在主服务器上写,只在从服务器上读。而从数据库处理SELECT查询操作。数据

库复制被用来把事务性操作导致的变更同步到集群中的从数据库。


②、为什么要读写分离呢?

因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。

但是数据库的“读”(读10000条数据可能只要5秒钟)。

所以读写分离,解决的是,数据库的写入,影响了查询的效率。

③、读写分离作用

数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用。

利用数据库主从同步,再通过读写分离可以分担数据库压力,提高性能。

2、实现方式

读写分离有两种实现方式:基于程序代码内部实现 和 基于中间代理层实现。

①、基于程序代码内部实现

在代码中根据 select、insert,进行路由分类,这类方法也是目前生产环境应用最广泛的。

优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支; 缺点是需要开发人

员来实现,运维人员无从下手。

但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的 Java 应用,如果在

程序代码中实现读写分离对代码改动就较大。

②、基于中间代理层实现

代理一般位于客户端和服务器之间, 代理服务器接到客户端请求后通过判断后转发到后端数据

库, 有以下代表性程序:

◆ MySQL-Proxy :MySQL-Proxy 为 MySOL开源项目, 通过其自带的 lua 脚本进行SOL 判断。

◆ Atlas:是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项

目。它是在mysql-proxy0.8.2版本的基础上,对其进行了优化, 增加了一些新的功能特性。360内

部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以 及存储过程。

◆ Amoeba:由陈思儒开发,作者曾就职于阿里巴巴。该程序由Jaya语言进行开发,阿里巴巴将其

用于生产环境。但是它不支持事务和存储过程。

由于使用 MySQL Proxy 需要写大量的 Lua 脚本,这些 Lua 并不是现成的,而是需要自己去写。

这对于并不熟悉 MySQL Proxy 内置变量和 MySQL Protocol 的人来说是非常困难的。Amoeba是

一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层。

四、MySQL 读写分离架构搭建

1、前期准备

①、安装Java 环境。因为 amoeba 是基于 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,

高版本不建议使用。

[root@amoeba opt]# ls /opt/    #在opt目录下准备amoeba和jdk的安装包
amoeba-mysql-binary-2.2.0.tar.gz
jdk-6u14-linux-x64.bin
mysql-5.7.17
rh
[root@amoeba opt]# cp jdk-6u14-linux-x64.bin /usr/local/
[root@amoeba opt]# cd /usr/local/
[root@amoeba opt]# chmod +x jdk-6u14-linux-x64.bin #赋予执行权限
[root@amoeba opt]# ./jdk-6u14-linux-x64.bin  #执行
#按住Enter,提示输入YES等待完成并回车
[root@amoeba local]# mv jdk1.6.0_14/ /usr/local/jdk1.6
#编辑全局配置文件,在最后一行添加以下配置
export JAVA_HOME=/usr/local/jdk1.6    #输出定义Java的工作目录
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib #输出指定的java类型
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin#将java加入路径环境变量
export AMOEBA_HOME=/usr/local/amoeba   #输出定义amoeba工作目录
export PATH=$PATH:$AMOEBA_HOME/bin  #加入路径环境变量

[root@amoeba ~]# source /etc/profile  #刷新文件
[root@amoeba ~]# java -version #查看java版本信息以检查是否安装成功
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)
[root@amoeba ~]#
②、安装 Amoeba
[root@amoeba ~]# mkdir /usr/local/amoeba
[root@amoeba ~]# tar zxvf /opt/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@amoeba ~]# chmod -R 755 /usr/local/amoeba/  #为目录赋予权限
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba   #开启amoeba
amoeba start|stop
[root@amoeba ~]#  #如显示amoeba start|stop说明安装成功

2、配置 amoeba 读写分离,之前两个 slave做读负载均衡

#首先、在master、slave1、slave2 的 mysql上开放权限给 amoeba 访问

mysql> grant all on *.* to test@'192.168.110.%' identified by '123456';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql>
#接着、回到amoeba 服务器配置 amoeba 服务
[root@amoeba ~]# cd /usr/local/amoeba/conf/   
[root@amoeba conf]# cp amoeba.xml amoeba.xml.bak  #先备份配置文件
[root@amoeba conf]# cp dbServers.xml dbServers.xml.bak
[root@amoeba conf]# cd
[root@amoeba ~]# vim /usr/local/amoeba/conf/amoeba.xml  #修改amoeba配置文件
……
#--30行--
<property name="user">amoeba</property>
#--32行-- 
<property name="password">123456</property>
#--115行--
<property name="defaultPool">master</property>
#--117行-120行,取消注释并修改
<property name="writePool">master</property>
<property name="readPool">slaves</property>
……

[root@amoeba ~]# vim /usr/local/amoeba/conf/dbServers.xml  #修改数据库配置文件
……
#--23行--注释掉  作用:默认进入 test 库,以防 mysql 中没有 test 库时会报错
<!-- <property name="schema">test</property> -->
#--26--修改,使用之前创建的授权用户
<property name="user">test</property>
#--29--去掉注释,密码为之前创建的授权用户密码
<property name="password">123456</property>
#--45--修改,设置主服务器的名 master
<dbServer name="master"  parent="abstractServer">
#--48--修改,设置主服务器的地址
<property name="ipAddress">192.168.10.20</property>
#--52--修改,设置从服务器的名 slave1
<dbServer name="slave1"  parent="abstractServer">
#--55--修改,设置从服务器1的地址
<property name="ipAddress">192.168.10.30</property>
#--58--复制上面 6 行粘贴,设置从服务器 2 的名 slave2 和地址
<dbServer name="slave2"  parent="abstractServer">
<property name="ipAddress">192.168.10.40</property>
#--65行--修改
<dbServer name="slaves" virtual="true">
#--71行--修改
<property name="poolNames">slave1,slave2</property>
......
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba start & # #启动 amoeba 软件,按 ctrl+c 返回
[root@amoeba ~]# netstat -anpt | grep java	 #查看 8066 端口是否开启,默认端口为 TCP 8066

3、客户端测试读写分离

###################客户端验证,修改数据库###########
[root@localhost ~]# yum install -y mariadb-server mariadb   #客户端安装
[root@localhost ~]# systemctl start mariadb.service
[root@localhost ~]# mysql -u amoeba -p123456 -h 192.168.110.128 -P8066 #通过中继服务器访问数据库
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 696318316
……
MySQL [(none)]> show databases;     
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
5 rows in set (0.01 sec)
MySQL [(none)]> use test;
MySQL [(none)]> create table test(id int,name char(20));
MySQL [test]> create table test001(id int,name char(20));
MySQL [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| test           |
| test001        |
+----------------+
2 rows in set (0.00 sec)

MySQL [test]>
#################master查看#####################
mysql> use test;
……
Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| test           |
| test001        |
+----------------+
2 rows in set (0.00 sec)
mysql>  #可以看到客户端添加的表,在主服务器上面都可以看到
#################slave1和slave2查看#####################
#显示结果与主服务器相同,可以看到客户端中做出的修改,在所有服务器上都能看到。

4、关闭 slave 功能后在主从服务器插入数据

从服务器关闭从服务功能,并添加记录,

 主服务器添加记录

 客户端验证

结论:客户端在 slave1、slave2 中轮询查看数据。由于从服务器都关闭了 slave 功能,因此无法

查看 master 服务器中的修改。

5、关闭 slave 功能后,客户端服务器写入数据

紧接着上述做,现在在客户端进行修改数据

 在master服务器查看

 在两台从服务器查看表内容

 

结论:客户端服务器的修改操作是对于 master 服务器进行的,因此 master 服务器上可以看到客

户端服务器所做的 insert 操作。由于客户端服务器的 select 操作是对从服务器进行的,而从服务

器关闭了 slave 功能,无法获取更新,因此客户端本身以及从服务器都无法查看更新操作。

6、从服务器开启 slave 服务

首先,开启从服务,并查看数据是否同步

 

 接着,在master主服务器查看

客户端查看表内容变化

 

结论:从服务器开启 slave 服务后可以从 master 服务器上获取更新,但是从服务器上的更新不会

被 master 服务器更新。客户端可以看到从服务器内容更新,但是是以轮询方式显示。

7、客户端服务器再次插入数据

客户端插入新数据

 

 master主服务器查看表内容

两台slave从服务器

 两台slave从服务器

 

结论:客户端服务器上的数据修改,会同步到所有服务器中。

总结

MySQL主服务器在用户增删改查提交事务的以后,会按顺序写入到binlog中,从服务器开启了 I/O

线程并请求binlog的内容,当binlog日志发生更新时,dump线程读取内容并推送给I/O线程。

从服务器连接主服务器数据库,I/O线程接收到binlog日志内容后会把数据放入本地中继日志中,

SQL线程会读取中继日志中的内容,并根据当中的内容对服务器进行操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值