MySQL 主从复制与读写分离

概念

主从复制与读写分离的意义

企业中的业务通常数据量都比较大,而单台数据库在数据存储、安全性和高并发方面都无法满足实际的需求,所以需要配置多台主从数据服务器,以实现主从复制,增加数据可靠性,读写分离,也减少数据库压力和存储引擎带来的表锁定和行锁定问题。

mysql支持的复制类型

(1) STATEMENT:基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制(5.7版本之前),执行效率高。高并发的情况可能会出现执行顺序的误差,事务的死锁。

(2)ROW:基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一 遍。精确,但效率低,保存的文件会更大。

(3)MIXED:混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。更智能,所以大部分情况下使用MIXED。

主从复制的工作过程

Master节点需要开启二进制日志,Slave节点需要开启中继日志。

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

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

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

MySQL主从复制的几个同步模式

1、异步复制(Asynchronous replication)

MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。

2、全同步复制(Fully synchronous replication)

指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。

3、半同步复制(Semisynchronous replication)

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

主从复制案例

每台服务器关闭防火墙和selinux

 systemctl disable --now firewalld
 setenforce 0

1)主服务器使用本地时钟源。

#安装时间同步工具(本地设置时钟源)
[root@localhost ~]# yum install -y ntp

#修改ntp配置文件,在末尾加入 
[root@localhost ~]# vim /etc/ntp.conf 
server 127.127.20.0              #设置本地时钟源,注意修改网段(72是网段)  
fudge 127.127.20.0 stratum 8     #设置时间层级为8(限制在15以内)  ​  
#开启ntpd 
[root@localhost ~]# systemctl start ntpd

2)两台从服务器同步主服务器的时间。

#安装时间同步工具
 yum install -y ntp
 #开启ntpd
 systemctl start ntpd
 ​
 #和主服务器进行时间同步
 /usr/sbin/ntpdate 192.168.161.153
 ​
 #设置定时任务,每30分钟同步一次
 crontab -e  
 */30 * * * * /usr/sbin/ntpdate 192.168.161.153

主服务器的mysql配置

修改配置文件,创建一个同步账号授权给从数据库使用。

[root@localhost ~]# vim /etc/my.cnf
 [mysqld]
 ......
 server-id = 1               #指定服务ID号,master和两台slave都要不同
 log-bin=mysql-bin           #添加,主服务器开启二进制日志
 binlog_format = MIXED       #指定二进制日志(binlog)的记录格式为MIXED
 log-slave-updates=true      #添加,允许slave从master复制数据时可以写入到自己的二进制日志
 expire_logs_days = 7        #设置二进制日志文件过期时间,默认值为0,表示logs不过期
 max_binlog_size = 500M      #设置二进制日志限制大小,如果超出给定值,日志就会发生滚动,默认值是1GB
 ​
 #重启服务
 [root@localhost ~]# systemctl restart mysqld
 ​
 [root@localhost ~]# mysql -u root -p
 #给从服务器授权
 grant replication slave on *.* to 'myslave'@'192.168.161.%' identified by '123123';  
 flush privileges;               #刷新权限
 ​
 show master status;     #查看主服务器状态
 //显示如下
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000008 |      604 |              |                  |
+------------------+----------+--------------+------------------+

 1 row in set (0.00 sec)
 ​
 #File 列显示日志名,Position 列显示偏移量

从服务器的mysql配置

Slave1 服务器:192.168.161.151,mysql5.7

Slave2 服务器:192.168.161.152,mysql5.7

从服务器的mysql配置
Slave1 服务器:192.168.161.151,mysql5.7
Slave2 服务器:192.168.161.152,mysql5.7
ini复制代码 #修改配置文件
 [root@localhost ~]# vim /etc/my.cnf
 [mysqld]
 ......
 server-id = 2            #修改,注意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 从库上开启该功能,建议开启。
 ​
 #重启服务
 [root@localhost ~]# systemctl restart mysqld     
 ​
 #登录数据库,进行同步设置
 [root@localhost ~]# mysql -u root -p
 CHANGE master to master_host='192.168.161.153',master_user='myslave',master_password='123123',master_log_file='mysql-bin.000008',master_log_pos=604;     
 #配置同步,注意 master_log_file 和 master_log_pos 的值要与Master查询的一致
 ​
 start slave;                #启动同步,如有报错执行 reset slave;
 ​
 show slave status\G         #查看 Slave 状态
 ##确保 IO 和 SQL 线程都是 Yes,代表同步正常。
 Slave_IO_Running: Yes               #负责与主机的IO通信
 Slave_SQL_Running: Yes              #负责自己的slave mysql进程
 ​
 ##一般 "Slave_IO_Running: No" 的可能原因:
 1. 网络不通 
 2. my.cnf配置有问题(server-id重复)
 3. 密码、file文件名、pos偏移量不对 
 4. 防火墙没有关闭 

主从复制案例演示(半同步复制)

实验环境:

Master 服务器:192.168.161.153,mysql5.7

Slave1 服务器:192.168.161.151,mysql5.7

Slave2 服务器:192.168.161.152,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';
 ​

 show status like 'Rpl_semi_sync_slave_status';      #从数据库执行(此时可能还是OFF状态,需要在下一步重启IO线程后,从库半同步状态才会为ON)

 ​

 STOP SLAVE IO_THREAD;       #重启从数据库上的IO线程
 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 内,收到了从库的响应, 则主从又重新恢复为半同步复制。
 ​
相关推荐
看星猩的柴狗2 分钟前
密码学原理技术-第二章-Stream Ciphers
服务器·网络·密码学
dengjiayue2 分钟前
MySQL 性能瓶颈,为什么 MySQL 表的数据量不能太大?
数据库·mysql
席万里4 分钟前
【MySQL学习笔记】关于索引
笔记·学习·mysql
m0_7482323924 分钟前
python3 Flask应用 使用 Flask-SQLAlchemy操作MySQL数据库
数据库·mysql·flask
苹果醋330 分钟前
Vue3响应式数据: 深入分析Ref与Reactive
java·运维·spring boot·mysql·nginx
竹影卿心1 小时前
Java连接HANA数据库
java·数据库·windows
anddddoooo1 小时前
Kerberoasting 离线爆破攻击
网络·数据库·安全·microsoft·网络安全
time never ceases1 小时前
Elasticsearch安装和数据迁移
大数据·数据库·elasticsearch·es
存储服务专家StorageExpert1 小时前
墙裂推荐:console, CLI命令行和日志使用字体-Cascadia
运维·服务器·netapp存储·存储维护·emc存储
Just_Do_IT_OK2 小时前
Docker--MySql
mysql·docker·容器