Mysql-主从复制与读写分离

Mysql-主从复制与读写分离

1.MySQL主从复制与读写分离

1.1主从复制与读写分离

mysql使用主从复制的原因大概由一下三点:

1、在业务复杂的系统中,有这么一个情景,有一句sql语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。

2、做数据的热备

3、架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。

mysql主从复制原理

1.2 主从复制的过程

在主从复制过程中涉及到总共3个线程,两个日志

Master 二进制日志

SLAVE I/O线程

Master dump线程

SLAVE 中继日志

SLAVE SQL线程

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

(2)Slave节点会在一定时间间隔内对Master的二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/o线程请求Master的二进制事件。

(3)同时Master 节点为每个I/o线程启动一个dump线程,用于向其发送二进制事件,并保存至slave节点本地的中继日志(Relay log)中,Slave节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,即解析成sql语句逐一执行,使得其数据和Master节点的保持一致,最后I/0线程和SQL线程将进入睡眠状态,等待下一次被唤醒。

半同步模式:注意:5.7版本主多了一个ACK_collection线程接受从的ack确认信息

1.3主从复制的同步模式

1.3.1 异步复制:

异步复制是mysql 默认的同步方式
在master为slave开通账号密码、ip授权之后,slave 可以从master进行数据同步,主要依赖的是master的binlog日志

slave会启动两个线程,IO Thread 和 SQL Thread
IO Thread 负责从master拉取binlog 日志,并写入relay中继日志
SQL Thread 负责将relay中继日志中的变更进行重放,更新数据来达到跟master保持数据一致的目的

这个过程中,slave通过IO线程拉取binlog,master无需关注是否有slave需要同步,只做自己的事情,整个复制过程都是异步完成的,这个就是异步复制

异步复制的优势是性能好,缺点是数据的安全性比较差
在某一刻主从之间的数据差异可能较大,主机挂掉之后从机接管,可能会丢失一部分数据。

1.3.2半同步复制

master更新操作写入binlog之后会主动通知slave,slave接收到之后写入relay log 即可应答,master只要收到至少一个ack应答,则会提交事务

可以发现,相比较于异步复制,半同步复制需要依赖至少一个slave将binlog写入relay log,在性能上有所降低,但是可以保证至少有一个从库跟master的数据是一致的,数据的安全性提高。

对于数据一致性要求高的场景,可以采用半同步复制的同步策略,比如主库挂掉时,准备接管的那一个从库,对数据的一致性要求很比较高。

半同步复制的优点是数据的安全性好,缺点是性能比异步复制稍低

1.3.3 全同步复制

全同步复制跟半同步复制的区别是,全同步复制必须收到所有从库的ack,才会提交事务。
主库的事务提交依赖于后面所有的从库,这样一来性能就会明显得下降
除非是对所有从库数据一致性要求非常高的场景,否则我们一般不采用这种策略

全同步复制的数据一致性最好,但是性能也是最差的

mysql主从同步的三种模式_吴小佳同学的博客

2.实验步骤

2.1主从复制配置

环境:centos7

mysql版本:5.7.37

​ mysql主节点:192.168.80.20

​ mysql从节点1:192.168.80.25

​ mysql从节点2:192.168.80.30

mysql主节点设置

1.ntp服务配置
[root@mysql_master ~]# yum install ntp -y
······
[root@mysql_master ~]# vim /etc/ntp.conf
--末尾添加--
server 127.0.0.1							#设置本地是时钟源,注意修改网段,127.0.0.1是本地回环地址(127.网段中所有ip实际上都是本地回环地址)
fudge 127.0.0.1 stratum 8	                #设置时间层级为8(限制在15内)
--------------------------------------------------------------
2.mysql配置文件
[root@mysql_master ~]# vim /etc/my.cnf
[mysqld]
......
server-id = 1
log-bin=mysql-bin							#添加,主服务器开启二进制日志
binlog_format = MIXED
log-slave-updates=true						#添加,允许slave从master复制数据时可以写入到自己的二进制日志
expire_logs_days = 7						#设置二进制日志文件过期时间,默认值为0,表示logs不过期
max_binlog_size = 500M						#设置二进制日志限制大小,如果超出给定值,日志就会发生滚动,默认值是1GB

:wq
--------------------------------------------------------------
[root@mysql_master ~]# systemctl restart mysqld   #重启msyql服务,使配置生效
[root@mysql_master ~]# mysql -uroot -p            #登录mysql

mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.80.%' IDENTIFIED BY '123456';  #从服务授权

mysql> FLUSH PRIVILEGES;

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      603 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)
#File 列显示日志名,Position 列显示偏移量



mysql从节点1配置

1.ntp配置
[root@mysql_slave1 ~]# yum install ntp ntpdate -y
[root@mysql_slave1 ~]# service ntpd start
[root@mysql_slave1 ~]# /usr/sbin/ntpdate 192.168.80.20         #与主节点进行时间同步

[root@mysql_slave1 ~]# crontab -e
*/30 * * * * /usr/sbin/ntpdate 192.168.80.20
--------------------------------------------------------------
2.mysql配置
[root@mysql_slave1 ~]# vim /etc/my.cnf
server-id = 25								#修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin						#添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index		#添加,定义中继日志文件的位置和名称,一般和relay-log在同一目录
relay_log_recovery = 1                      #选配项
#当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log,并且重新从 master 上获取日志,这样就保证了 relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启。

:wq
--------------------------------------------------------------
[root@mysql_slave1 ~]# systemctl restart mysqld
[root@mysql_slave1 ~]# mysql -uroot -p

mysql> CHANGE master to master_host='192.168.80.20',master_user='myslave',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=603;           #日志名称与偏移点应该与主status中的相同
mysql> start slave;
mysql> show slave status\G                # 查看从状态
//确保 IO 和 SQL 线程都是 Yes,代表同步正常。
Slave_IO_Running: Yes				#负责与主机的io通信
Slave_SQL_Running: Yes				#负责自己的slave mysql进程

#一般 Slave_IO_Running: No/CONNECTING 的可能性:
1、网络不通
2、my.cnf配置有问题
3、密码、file文件名、pos偏移量不对
4、防火墙没有关闭

mysql从节点2配置需要修改server-id

实验截图

主节点配置

1.ntp服务相关配置
image
2.mysql配置文件
image
[mysqld]下加入
image

mysql从节点配置:

1.ntp时间同步设置
image
2.mysql配置
image

主从复制效果验证:

image
image
image

2.2 读写分离配置

环境:centos7

mysql版本:5.7.37

​ mysql主节点:192.168.80.20

​ mysql从节点1:192.168.80.25

​ mysql从节点2:192.168.80.30

​ Amoeba 服务器:192.168.80.35 jdk1.6、Amoeba

Amoeba服务器配置

实现准备jdk和amoeba包至opt目录
1.配置java环境
[root@amoeba opt]# cd /opt
[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
[root@amoeba opt]# ./jdk-6u14-linux-x64.bin
//按yes,按enter
[root@amoeba local]# mv jdk1.6.0_14/ /usr/local/jdk1.6

[root@amoeba 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@amoeba local]# source /etc/profile
[root@amoeba local]# java -version

2.配置Amoeba
[root@amoeba local]# cd /opt
[root@amoeba opt]# mkdir /usr/local/amoeba
[root@amoeba opt]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@amoeba opt]# chmod -R 755 /usr/local/amoeba/
[root@amoeba opt]# /usr/local/amoeba/bin/amoeba
##配置 Amoeba读写分离,两个 Slave 读负载均衡##
先将一主两从开放授权
grant all on *.* to test@'192.168.80.%' identified by '123.com';
#再回到amoeba服务器配置amoeba服务:
[root@amoeba opt]# cd /usr/local/amoeba/conf/
[root@amoeba opt]# cp amoeba.xml amoeba.xml.bak
[root@amoeba opt]# vim amoeba.xml		
--30行--
<property name="user">amoeba</property>
--32行-- 
<property name="password">123456</property>
--115行--
<property name="defaultPool">master</property>
--117-去掉注释-
<property name="writePool">master</property>
<property name="readPool">slaves</property>

:wq
--------------------------------------------------------------
[root@amoeba opt]# cp dbServers.xml dbServers.xml.bak
[root@amoeba opt]# vim dbServers.xml
--23行--注释掉  作用:默认进入test库 以防mysql中没有test库时,会报错
<!-- <property name="schema">test</property> -->
--26--修改
<property name="user">test</property>
--28-30--去掉注释
<property name="password">123.com</property>
--45--修改,设置主服务器的名Master
<dbServer name="master"  parent="abstractServer">
--48--修改,设置主服务器的地址
<property name="ipAddress">192.168.80.10</property>
--52--修改,设置从服务器的名slave1
<dbServer name="slave1"  parent="abstractServer">
--55--修改,设置从服务器1的地址
<property name="ipAddress">192.168.80.11</property>
--58--复制上面6行粘贴,设置从服务器2的名slave2和地址
<dbServer name="slave2"  parent="abstractServer">
<property name="ipAddress">192.168.80.12</property>
--65行--修改
<dbServer name="slaves" virtual="true">
--71行--修改
<property name="poolNames">slave1,slave2</property>

[root@amoeba opt]# /usr/local/amoeba/bin/amoeba start&    后台启动amoeba	
[root@amoeba opt]# netstat -anpt | grep java

实验截图

1.配置java环境
image
2.配置amoeba
image
先配置mysql一主两从开放授权

grant all on *.* to test@'192.168.80.%' identified by '123.com';
image
image
image
image

读写分离测试

主机通过Navicat连接数据库
image
主服务器上创建表
image
从1从2关闭主从复制
image
在slave1插入数据
image
在slave2插入数据
image
在master插入数据
image
Navicat查看表数据
image
关闭表刷新一次,在打开表test
image
插入一条数据
image
主查看数据
image
从1查看数据
image
从2查看数据
image
只有主能查看到插入的数据。

从2打开主从复制
image
可以看到客户端和主之前插入的数据了。
image
再次打开客户端查看,还是存在两种表记录的情况。
image
主服务器上还是只有客户端与主插入的数据。
image

posted @ 2022-06-05 21:15  残-云  阅读(661)  评论(0编辑  收藏  举报