MySQL半同步复制实践

1.主从复制原理

在MySQL主从复制中,大体上有三个线程,master端有一个dump 线程,slave端有两个线程,i/o 线程和sql线程。

当有数据写入后,master 端的dump线程将bin log发送到slave端的io线程,i/o线程接收后,将其存放在本地的relay log中。

sql线程读取relay log,接着重放 event,更新数据。

主从复制有三种方式:

  • 异步复制
  • 同步复制
  • 半同步复制

其中,同步复制中,master执行一个事务后,要求所有的slave都执行完成后,才会返回给客户端。这样,在性能上,是有影响的。同步复制的优势,就是不丢失数据。缺点,就是复制效率低。
MySQL自身不支持同步复制,需要用第三方工具如DRBD(sync模式)等实现同步复制。

异步复制中,master 更新操作写入binlog后,就会返回给客户端。不关心,slave 是否接收到binlog,以及是否应用了更新。异步复制的优势,是复制效率高。缺点是,可能会丢失数据。

半同步复制(semi-sync repication),是介于同步复制和异步复制之间的一种复制方式。主库在执行完客户端提交的事务之后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端(极端情况下,如果等待超时,会退化为异步复制)。相对于异步复制,半同步复制提高了数据的安全性。

2.半同步复制环境搭建

下文使用的是单机多实例环境,具体搭建过程可参考单机安装MySQL多实例

MySQL版本是 5.7.27。

MySQL主从集群信息如下:

角色ipport
主库127.0.0.13306
从库127.0.0.13307

2.1 半同步插件安装和配置

MySQL安装包中,已经自带MySQL半同步插件。

$ ll /application/mysql/lib/plugin/semi*
-rwxr-xr-x. 1 lanyang lanyang 708586 Jun 10  2019 /application/mysql/lib/plugin/semisync_master.so
-rwxr-xr-x. 1 lanyang lanyang 152341 Jun 10  2019 /application/mysql/lib/plugin/semisync_slave.so

2.1.1 主库半同步插件安装和配置

安装插件

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.01 sec)

mysql> 

主库开启半同步

mysql> set global rpl_semi_sync_master_enabled = 1;
Query OK, 0 rows affected (0.01 sec)

mysql> 

配置半同步超时参数(单位ms)

mysql> set global rpl_semi_sync_master_timeout = 1000;
Query OK, 0 rows affected (0.00 sec)

mysql> 

该参数表示主库等待从库ack的时间,如果超时,半同步复制就退化为异步复制。

此处配置的超时时间是1s。

在配置文件添加,使其永久生效:

[mysqld]
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 1000

查看半同步插件安装和配置状态

mysql> select * from mysql.plugin;
+----------------------+--------------------+
| name                 | dl                 |
+----------------------+--------------------+
| rpl_semi_sync_master | semisync_master.so |
+----------------------+--------------------+
1 row in set (0.00 sec)

主库半同步复制的状态参数

mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |
| 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)

其中,Rpl_semi_sync_master_clients 有多少个开启了半同步复制的从库。

Rpl_semi_sync_master_net_avg_wait_time master等待slave回复的平均网络等待时间。

Rpl_semi_sync_master_net_wait_time 总网络等待时间。

Rpl_semi_sync_master_net_waits master等待slave回复总的网络等待次数。

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_yes_tx 接收确认次数。

Rpl_semi_sync_master_no_times 关闭半同步复制的次数。

Rpl_semi_sync_master_no_tx 查看有多少事务没有使用半同步复制的机制进行复制,也就是master等待超时的次数。

主库半同步复制的相关参数配置

mysql> show global variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 1000       |
| 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)

其中,
rpl_semi_sync_master_wait_for_slave_count 表示主库事务提交前,在指定的时间rpl_semi_sync_master_timeout超时之前,必须有这个指定数量的从库确认已接收到。

如果超时之前,仍然没有得到rpl_semi_sync_master_wait_for_slave_count这个数量的从库确认,则退化为异步复制。

默认值1,即超时之前,需要有一个从库确认已接收到bin log,事务才可以提交。

对于
rpl_semi_sync_master_wait_no_slave,表示是否每个事务提交后都需要等待从库的接收确认信号。

如果为ON(默认是ON),只要指定数量的从库在超时之前确认已接收,则半同步复制会继续。

如果为OFF,表示在超时之前,没有达到指定数量从库已确认接收。则退化为异步复制。

2.1.2 从库半同步插件安装和配置

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.02 sec)

mysql> 

从库开启半同步

mysql> set global rpl_semi_sync_slave_enabled = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> 

添加到配置文件使其永久生效:

[mysqld]
rpl_semi_sync_slave_enabled = 1

配置后,记得重启下i/o线程。

查看从库上半同步复制状态和参数:

mysql> show global status like '%semi%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)
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.00 sec)

接着,查看主库上的半同步复制状态:

mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
+--------------------------------------------+-------+
... ...
14 rows in set (0.00 sec)

显示已有一个从库通过半同步复制连接到主库。

2.2 半同步复制测试

2.2.1 测试1–简单测试

在主库上写入两条数据:

mysql> insert into app.test(service_group_name) values('abc001');
Query OK, 1 row affected (0.01 sec)

mysql> insert into app.test(service_group_name) values('abc002');
Query OK, 1 row affected (0.00 sec)

查看主库上的半同步复制状态:

mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 2     |
| 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      | 472   |
| Rpl_semi_sync_master_tx_wait_time          | 472   |
| Rpl_semi_sync_master_tx_waits              | 1     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 2     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

mysql> 

2.2.2 测试2–超时测试

(1)停止从库的i/o线程

停止从库的i/o线程,可以使半同步复制超时。

mysql> stop slave io_thread;
Query OK, 0 rows affected (0.01 sec)

(2)在主库上写入数据

mysql> insert into app.test(service_group_name) values('abc003');
Query OK, 1 row affected (1.01 sec)

mysql> 

可以看到执行时间1.01s。

查看此时的半同步复制状态:

mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 2     |
| Rpl_semi_sync_master_no_times              | 1     |
| Rpl_semi_sync_master_no_tx                 | 1     |
| Rpl_semi_sync_master_status                | OFF   |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 472   |
| Rpl_semi_sync_master_tx_wait_time          | 472   |
| Rpl_semi_sync_master_tx_waits              | 1     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 2     |
+--------------------------------------------+-------+
14 rows in set (0.01 sec)

Rpl_semi_sync_master_no_times 关闭半同步的次数为1。

Rpl_semi_sync_master_no_tx 等待超时的次数,为1.

Rpl_semi_sync_master_status 半同步状态处于关闭状态。

(3)从库开启i/o 线程

mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)

(4)再次查看主库上半同步复制状态

mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 3     |
| Rpl_semi_sync_master_no_times              | 1     |
| Rpl_semi_sync_master_no_tx                 | 1     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 472   |
| Rpl_semi_sync_master_tx_wait_time          | 472   |
| Rpl_semi_sync_master_tx_waits              | 1     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 2     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

从库复制后,主库半同步复制状态又变为ON。

3.参考

16.1.6.2 Replication Source Options and Variables

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值