半同步复制

默认情况下,MySQL的复制功能是异步的,异步复制可以提供最佳的性能,主库把binlog日志发送给从库即结束,并不验证从库是否接收完毕。这意味着当主服务器或从服务器端发生故障时,有可能从服务器没有接收到主服务器发送过来的binlog日志,这就会造成主服务器和从服务器的数据不一致,甚至在恢复时造成数据的丢失。

MySQL5.5版本为了保证主从数据的一致性问题。加入了半同步复制的组件(插件),可以控制从库IO线程是否将relaylog落盘,一旦落盘通过插件返回ACK给主库ACK_REC。接受到ACK之后,主库的事务才能提交成功。在默认情况下,如果超过10秒没有返回ACK,此次复制行为会切换为异步复制。

在MySQL5.6,5.7 当中也加入了一些比较好的特性,也不能完全保证的数据一致。如果生产业务比较关注主从最终一致(比如:金融等)。推荐可以使用MGR的架构,或者PXC等一致性架构。

图片[1]-半同步复制-李佳程的个人主页
# 半同步复制默认设置
rpl_semi_sync_master_wait_point=after_commit
图片[2]-半同步复制-李佳程的个人主页
  • 缺点1: 幻读
    • 当用户提交一个事务,该事务已经写入redo日志和binlog日志,但该事务还没写入从库,此时处在waiting slave dump处,此时另一个用户可以读取到这条数据,而他自己却不能;
  • 缺点2:数据丢失
    • 一个提交的事务在waiting slave dump处crash后,主库将比从库多一条数据
# 增强半同步复制(MySQL5.7新增功能)
rpl_semi_rsync_master_wait_point=after_sync
图片[3]-半同步复制-李佳程的个人主页
  • 改善1:解决幻读
    • 当用户发起一个事务,该事务先写入二进制后,再向从库进行同步,由于还没有完成提交,此时其他用户无法读取到该数据,解决了幻读
  • 改善2:解决数据丢失
    • 一个事务在waiting slave dump处crash掉后,可以通过观察从库上是否存在主库的last gtid值,如果存在,这条数据正常恢复,如果不存在则删除主库的那条多余的GTID值,然后恢复,保证了数据的完整性

在MySQL8.0 实现半同步复制

# master服务器配置
[root@centos79-mysql01 ~]# vim /etc/my.cnf
[mysqld]
server-id=21
log-bin
rpl_semi_sync_master_enabled=ON        #需要先安装semisync_master.so插件后,再重启
rpl_semi_sync_master_timeout=3000      #设置3s内无法同步,也将返回成功信息给客户端

# 永久安装插件
[root@centos79-mysql01 ~]# mysql -uroot -p123456
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';

# 重启服务
[root@centos79-mysql01 ~]# service mysqld restart

mysql> create user copyuser@'192.168.%' identified by '123456';

mysql> grant replication slave on *.* to copyuser@'192.168.%';
mysql> show master logs;
+-----------------------------+-----------+-----------+
| Log_name                    | File_size | Encrypted |
+-----------------------------+-----------+-----------+
| centos79-mysql01-bin.000001 |       180 | No        |
| centos79-mysql01-bin.000002 |       518 | No        |
| centos79-mysql01-bin.000003 |     11501 | No        |
+-----------------------------+-----------+-----------+
3 rows in set (0.00 sec)



# 从服务器1配置
[root@centos79-mysql02 ~]# vim /etc/my.cnf

[mysqld]
server-id=22
rpl_semi_sync_slave_enabled=ON     #需要先安装semisync_slave.so插件后,再重启

# 永久安装插件
[root@centos79-mysql02 ~]# mysql -uroot -p123456
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

# 重启服务
[root@centos79-mysql02 ~]# service mysqld restart

# 使用复制用户请求服务器公钥
mysql -ucopyuser -p123456 -h192.168.1.21 --get-server-public-key

# 配置从主服务器同步
[root@centos79-mysql02 ~]# mysql -uroot -p123456
mysql> CHANGE MASTER TO   MASTER_HOST='192.168.1.21',MASTER_USER='copyuser',MASTER_PASSWORD='123456',MASTER_PORT=3306,MASTER_LOG_FILE='centos79-mysql01-bin.000003',MASTER_LOG_POS=157;

mysql> start slave;



# 从服务器2配置
[root@centos79-mysql03 ~]# vim /etc/my.cnf
[mysqld]
server-id=23
rpl_semi_sync_slave_enabled=ON     #需要先安装semisync_slave.so插件后,再重启

# 永久安装插件
[root@centos79-mysql03 ~]# mysql -uroot -p123456
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

# 重启服务
[root@centos79-mysql03 ~]# service mysqld restart

# 使用复制用户请求服务器公钥
mysql -ucopyuser -p123456 -h192.168.1.21 --get-server-public-key

# 配置从主服务器同步
[root@centos79-mysql03 ~]# mysql -uroot -p123456
mysql> CHANGE MASTER TO   MASTER_HOST='192.168.1.21',MASTER_USER='copyuser',MASTER_PASSWORD='123456',MASTER_PORT=3306,MASTER_LOG_FILE='centos79-mysql01-bin.000003',MASTER_LOG_POS=11501;

mysql> start slave;
# 主服务器查看状态
mysql>  show 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> SHOW STATUS LIKE 'Rpl_semi_sync%';
+--------------------------------------------+-------+
| 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             | 1     |
| Rpl_semi_sync_master_no_times              | 2     |
| Rpl_semi_sync_master_no_tx                 | 38    |
| 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)

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享