异步复制
MySQL 默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主节点如果 crash 掉了,此时主节点上已经提交的事务可能并没有传到从库上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
全同步复制
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
半同步复制( 半异步复制 )
是介于全同步复制与全异步复制之间的一种,主库只需要等待至少一个从库节点收到并且 Flush Binlog 到 Relay Log 文件即可,主库不需要等待所有从库给主库反馈。同时,这里只是一个收到的反馈,而不是已经完全完成并且提交的反馈,如此,节省了很多时间。
时间阈值概念:如果主节点服务器仅同步数据到其中一个从节点速度也很慢。( 比如设置超时阈值 10S ,从节点 10S 没有数据同步完成并反馈结果,主节点会直接将结果返回客户端。不等你从节点完成同步了。 )
范例:CentOS8 在 MySQL8.0 实现半同步复制
注意:每个数据库版本半同步复制的方法有所不同
建议:
二进制日志格式( ROW 行类型 )
所有节点都开启二进制日志功能( 并将二进制日志文件分开存放 )
所有从节点开启只读功能( read-only )
// 前置工作
yum install mysql-server -y
systemctl enable --now mysqld
// 创建二进制日志目录
mkdir /data/log/mysql -p
chown -R mysql:mysql /data/log/mysql
// 关闭防火墙 and SELinux
setenforce 0
systemctl disable --now firewalld
# 查看插件文件 ( 库文件 )
[root@master ~] rpm -ql mysql-server | grep semisync
/usr/lib64/mysql/plugin/semisync_master.so
/usr/lib64/mysql/plugin/semisync_replica.so
/usr/lib64/mysql/plugin/semisync_slave.so
/usr/lib64/mysql/plugin/semisync_source.so
# master 服务器配置
[root@master ~] vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
server-id=8
log-bin
rpl_semi_sync_master_enabled=ON # 修改此行, 需要先安装 semisync_master.so 插件后, 再重启, 否则无法启动 ( 开启主节点的半同步功能 )
rpl_semi_sync_master_timeout=3000 # 超时阈值: 设置 3s 内无法同步, 也将返回成功信息给客户端 ( 默认: 10S )
// 创建账户并授权
mysql> show master logs; # 查看位置
+---------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 | 156 | No |
+---------------+-----------+-----------+
1 row in set (0.00 sec)
mysql> create user repluser@'192.168.80.%' identified by '123456';
mysql> grant replication slave on *.* to 'repluser'@'192.168.80.%';
// slave1 服务器配置
[root@slave1 ~] vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
server-id=18
rpl_semi_sync_slave_enabled=ON # 修改此行, 需要先安装 semisync_slave.so 插件后, 再重启, 否则无法启动 ( 插件开机自启 )
// slave2 服务器配置
[root@slave2 ~] vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
server-id=28
rpl_semi_sync_slave_enabled=ON # 修改此行, 需要先安装 semisync_slave.so 插件后, 再重启, 否则无法启动 ( 插件开机自启 )
// 主服务器配置:
mysql> SHOW PLUGINS; # 查看插件
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; # 永久安装插件
mysql> SET GLOBAL rpl_semi_sync_master_enabled=1; # 临时修改变量
mysql> SET GLOBAL rpl_semi_sync_master_timeout = 3000; # 超时长 3S, 默认值为 10s
mysql> SHOW GLOBAL VARIABLES LIKE '%semi%';
+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 3000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.00 sec)
// 从节点连接主节点 ( "两台从节点都配置" )
mysql> CHANGE MASTER TO
MASTER_HOST='192.168.80.8',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=156;
// 从服务器配置 ( "两个从节点都需要安装好插件" )
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql> SET GLOBAL rpl_semi_sync_slave_enabled=1; # 临时修改变量
mysql> SHOW GLOBAL VARIABLES LIKE '%semi%'; # 验证从服务器插件启用状态
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
2 rows in set (0.01 sec)
// 从节点重启数据库服务
[root@slave1 ~] systemctl restart mysqld
[root@slave2 ~] systemctl restart mysqld
# 注意: 如果已经实现主从复制, 需要 stop slave;start slave;
mysql> start slave;
mysql> SHOW GLOBAL STATUS LIKE '%semi%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.01 sec)
// 主节点查看从节点状态
mysql> SHOW GLOBAL STATUS LIKE '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 2 | # 数量
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
// 验证线程
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 192.168.80.8
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000001
Read_Master_Log_Pos: 689
Relay_Log_File: centos8-relay-bin.000003
Relay_Log_Pos: 854
Relay_Master_Log_File: binlog.000001
Slave_IO_Running: Yes # 运行中
Slave_SQL_Running: Yes
# 运行中
// 验证半同步复制
mysql> create database db1; # 主节点
mysql> show databases; # 从节点
mysql> show databases; # 从节点
// "测试效果"
stop slave; # 两个从节点停止复制线程
stop slave; # 两个从节点停止复制线程
create database db2; # 主节点创建数据库 ( 三秒后自动完成创建 因为超过了阈值 )
start slave; # 两个从节点启用复制线程
start slave; # 两个从节点启用复制线程