mysql8 进阶(三) 主从复制之半同步复制

前面的文章介绍了 mysql 中主从复制的实践原理,不过前面的主从复制是 mysql 的默认复制方式:异步复制。本文主要介绍半同步复制的原理与实现。

1 异步复制的问题

在复制过程当中,主库不会去验证 bin-log 有没有成功复制到从库。如果主库提交一个事务并写入 bin-log 中后,由于网络原因,从库没有接收到对应的 bin-log 那从库就不会得到这个事务,也就造成了主从数据的不一致。

2 半同步复制

在半同步模式中一个事务的执行流程如下:

在这里插入图片描述

1、主库收到客户端提交的事务。
2、主库执行事务。
3、将数据库事件写入到主库的 bin-log 日志中。
4、当从库来请求 bin-log 日志时,将其发送给从库。
5、从库的 I/O 线程获取到的 bin-log 日志写入到 relay-log 中。
6、当 relay-log 写入完成后,从库向主库发送一个写入成功的通知
7、主库收到从库发来的成功通知后将事务的结果返回给客户端。
8、从库的 SQL 线程对写入成功的 relay-log 进行重放,将数据保存到数据库中。
当然,在半同步复制中第 7 步与第 8 步是异步的。所以这里有同步有异步,姑且我们就叫它半同步复制(Semisynchronous Replication)吧。

同步体现在主库返回事务结果给客户端时,须收到从库发送的 relay-log 写入成功的通知才能返回,否则会一直等待从库发来通知,直到等待时间到了(rpl_semi_sync_master_timeout 参数设置的值)。

异步体现在主库只要收到从库发来的成功通知即可返回结果给客户端,不需要考虑从库的 relay-log 是否重放成功。

假如主库在执行第 1、2、3 步的任意一步步骤时主库宕机,事务都不会成功,自然从库也不会收到主库发送的 bin-log,所以主从的数据还是保持一致。

假如执行第 4步时,主库宕机事务也不会提交成功,如果由于网络原因导致从库未接收到主库的 bin-log 日志,则主库会等待从库一段时间(等待从库写入 relay-log 成功的通知 ACK),然后将主从复制的模式切换到异步模式,再返回成功给客户端

假如执行第 5 步时,主库宕机由于此时主库还在等待从库,则主库事务自然执行失败。如果从库宕机则主库会等待从库,若一段时间后未收到 ACK,则将主从复制的模式切换到异步模式,再返回成功给客户端。

3 搭建半同步复制

搭建半同步复制的过程很简单,只需要在主节点、从节点上分别安装一个半同步复制的插件和配置两个参数即可。

我们在前面的主从复制实践文章的基础上来搭建半同步复制。

这是我们前面搭建的主从复制的两个 mysql 容器:
在这里插入图片描述

3.1 主节点

首先进入主节点安装半同步复制的插件:rpl_semi_sync_master

1、进入 mysql_master 容器,查看是否已安装 rpl_semi_sync_master 插件:

show plugins;

在这里插入图片描述
图中没有 rpl_semi_sync_master 插件。

2、安装插件:

install plugin rpl_semi_sync_master soname 'semisync_master.so';

在这里插入图片描述
再次查看已安装的插件列表:
在这里插入图片描述
可以看到半同步插件在主节点上已经安装完成了。

3、修改配置文件
在 my.cnf 配置文件中增加 rpl_semi_sync_master_enabled=1 参数:

[mysqld]
init_connect='set collation_connection=utf8mb4_unicode_ci; set names utf8mb4;'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
server-id=1 #重要,主节点的 server-id 不能与从节点相同
log-bin=mysql-bin
binlog-ignore-db=mysql
binlog_cache_size=1M
binlog_format=mixed
expire_logs_days=7
#开启半同步复制
rpl_semi_sync_master_enabled=1
3.2 从节点

从节点与主节点的操作步骤一样,先安装半同步复制插件,再添加一个配置即可。

1、安装插件:

install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

2、配置文件

[mysqld]
init_connect='set collation_connection=utf8mb4_unicode_ci; set names utf8mb4;'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
server-id=2
log-bin=mysql-slave-bin
binlog-ignore-db=mysql
relay_log=mysql-relay-bin
binlog_cache_size=1M
binlog_format=mixed
expire_logs_days=7
slave_skip_errors=1062
read_only=1
log_slave_updates=1
#开启半同步复制
rpl_semi_sync_slave_enabled=1
3.3 重启主从服务器

主从节点的插件与配置修改完成后重启容器就可开启半同步复制了。

#重启主节点
docker restart mysql_master
#重启从节点
docker restart mysql_slave

重启完成后查看半同步复制是否已开启:
在主库上执行:show status like ‘%rpl_semi%’;
在这里插入图片描述
Rpl_semi_sync_master_status 为 ON 表示半同步复制已开启。

Rpl_semi_sync_master_clients 为 1 表示当前有 1 个从节点连接着这主节点。

在从库上执行:show status like ‘%rpl_semi%’;
在这里插入图片描述
到此为止,半同步复制就搭建完成了,我们可以在主库上添加一些数据,来验证一下数据是否复制到从库上。

4、常用配置

1、rpl_semi_sync_master_enabled=1 表示主库开启半同步复制。默认为 0 ,即关闭半同步复制。

2、rpl_semi_sync_master_timeout=10000 ,单位为毫秒,默认为 10000。用于配置主库等待从库写入 relay-log 日志成功的 ACK 通知的时间。若超过该时间主库将主从模式切换为异步模式,并返回事务提交成功给客户端

我们来简单的模拟一下:

首先停掉从节点:

docker stop mysql_slave

然后在主节点中增加一条数据:
在这里插入图片描述
我们可以看到这条语句执行了 10.06 秒,其中有 10 秒都是在等待接收从库的 ACK 。此时再去查看半同步复制状态就变成关闭状态了:
在这里插入图片描述
但此时主库是异步复制模式。

最后启动从库,即可恢复半同步复制模式。再去查看从库中的数据,会发现刚刚在主库添加的数据也同步到从库了。

3、rpl_semi_sync_master_wait_for_slave_count=1 表示主库收到 1 个从库发来的 ACK 就返回事务提交成功。默认为 1 。这个参数一般与 rpl_semi_sync_master_wait_no_slave 参数配合使用,默认为 ON。

  • rpl_semi_sync_master_wait_no_slave 为 ON 时,允许 Rpl_semi_sync_master_clients(半同步复制的 slave 数量) 在超时时间内(rpl_semi_sync_master_timeout)不低于 rpl_semi_sync_master_wait_for_slave_count 的值那么半同步复制不会自动切换为异步复制;若在超时时间达到时还低于则会切换为异步复制切换为异步复制后,若在某一时间从库的连接数 Rpl_semi_sync_master_clients 大于等于了 rpl_semi_sync_master_wait_for_slave_count 的值,则又会自动从异步模式切换为半同步模式且会向这些从节点发送未被复制的 bin-log。其实前面 rpl_semi_sync_master_timeout 的实验就可以证明这一点。
  • rpl_semi_sync_master_wait_no_slave 为 OFF 时,只要 Rpl_semi_sync_master_clients 的值于 rpl_semi_sync_master_wait_for_slave_count 的值,主从复制的模式就会立即切换为异步模式。

4、rpl_semi_sync_master_wait_point=AFTER_SYNC ,用于配置主库在哪个点(什么时机)等待接收从库的 ACK 通知。默认为 AFTER_SYNC

  • AFTER_SYNC 表示主库在 bin-log 被 flush 之后,在存储引擎 commit 前进入等待,这可以保证数据在被复制到从库前不被其他会话(客户端)可见。假如现在主库有 A、B 两个会话(客户端)连接着,A 修改了一些数据,那么在主库收到从库的 ACK 前,这些数据还没有 commit 到主库的存储引擎中,所以 B 会话还看不到更改后的数据。

  • AFTER_COMMIT 表示主库 bin-log 被 flush 之后并在存储引擎 commit 之后进入等待,尽管发起 commit 的会话还未收到 commit 成功的结果,其他的会话已经可以看到 commit 后的数据了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值