增强半同步复制

一、理解半同步

1、概念

MySQL默认的复制都是异步的,在服务器崩溃时丢失事务是使用异步复制不可避免的结果。而5.5之后推出的一项新功能:半同步复制,可以限制事务丢失的数量。

1>异步复制

Asynchronous replication

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

2>全同步复制

Fully synchronous replication

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

3>半同步复制

Semisynchronous replication

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

2、MySQL5.7在5.6/5.5的基础上增强了几点功能

1>无数据丢失

MySQL5.7在Master事务提交的时间方面做了改进(rpl_semi_sync_master_wait_point:AFTER_COMMIT\AFTER_SYNC),事务是在提交之前发送给Slave(默认:after_sync),当Slave没有接收成功,并且Master宕机了,不会导致主从不一致,因为此时主还没有提交,所以主从都没有数据。

MySQL5.7也支持和MySQL5.5\5.6一样的机制:事务提交之后再发给Slave(after_commit)****。

总之,MySQL5.7半同步的好处就是在确认事务复制到Slave之前,并发的其他线程看不到当前事务的数据。当Master故障时,要么提交的事务已经复制到Slave,要么全部都没提交,这样就保证了数据的一致性。

2>更快的半同步复制

MySQL5.5/5.6的半同步复制是一个单工通讯方式,master把事务发送完毕后,要接收和处理slave的应答,处理完应答之后才能继续发送下一个事务。

MySQL5.7的半同步复制创建了单独的应答接收线程,变成了双工模式,发送和接收互不影响。因为有了相应的线程处理,发送效率得到大幅提升,相比MySQL5.5/5.6延迟会小很多,性能得到大幅提升。

5.7 semi_sync具体设计思路如下:

  1. 事务提交的时候,主库把 binlog 发给从库;
  2. 从库收到 binlog 以后,发回给主库一个 ack,表示收到了;
  3. 主库收到这个 ack 以后,才能给客户端返回“事务完成”的确认。

也就是说,如果启用了 semi-sync,就表示所有给客户端发送过确认的事务,都确保了备库已经收到了这个日志。

注意:

MySQL5.7单独的应答接收线程在开启半同步复制的时候默认就创建了,不需要额外的设置。

3>等待多个slave应答

在半同步复制中,Master发送事务默认至少有一个Slave得到响应才能继续下一个事务。MySQL5.7之后用户可以设置应答的Slave数量,并且可以通过参数(rpl_semi_sync_master_wait_for_slave_count)。该变量控制slave应答的数量,默认是1,表示master接收到几个slave应答后才commit。在多从的环境下,设置大于1可以提高数据的可靠性。

二、参数说明

1、主库

rpl_semi_sync_master_enabled

表示主上是否开启半同步复制功能,可以动态修改。可选值:ON\OFF

rpl_semi_sync_master_timeout

为了防止半同步复制中主在没有收到S发出的确认发生堵塞,用来设置超时,超过这个时间值没有收到信息,则切换到异步复制,执行操作。默认为10000毫秒,等于10秒,这个参数动态可调,表示主库在某次事务中,如果等待时间超过10秒,那么则降级为异步复制模式,不再等待SLAVE从库。如果主库再次探测到,SLAVE从库恢复了,则会自动再次回到半同步复制模式。可以设置成1000,即1秒。

rpl_semi_sync_master_wait_for_slave_count

控制slave应答的数量,默认是1,表示master接收到几个slave应答后才commit。

rpl_semi_sync_master_wait_no_slave

当一个事务被提交,但是Master没有Slave连接,这时M不可能收到任何确认信息,但M会在时间限制范围内继续等待。如果没有Slave链接,会切换到异步复制。是否允许master每个事务提交后都要等待slave的接收确认信号。默认为on,每一个事务都会等待。如果为off,则slave追赶上后,也不会开启半同步复制模式,需要手工开启。

rpl_semi_sync_master_wait_point

该参数表示半同步复制的主在哪个点等待从的响应,默认AFTER_SYNC,在得到slave的应答后再commit,可选值AFTER_COMMIT。

2、从库

rpl_semi_sync_slave_enabled

表示从上是否开启半同步复制功能,可以动态修改。可选值:ON\OFF

Rpl_semi_sync_slave_status

Slave上的半同步复制状态,ON表示已经被启用,OFF表示非活动状态。

rlp_semi_sync_slave_trace_level=32

表示开启半同步复制模式时的调试级别,默认是32。

三、安装部署

本次部署演示环境为

  • 操作系统:CentOS7.2
  • 数据库:   MySQL5.7.24
  • 复制模式:GTID + ROW 

1、环境准备

要想使用半同步复制,必须满足以下几个条件

  1. MySQL 5.5及以上版本
  2. 变量have_dynamic_loading为YES
  3. 异步复制已经存在
mysql> show variables like '%have_dynamic_loading%';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| have_dynamic_loading | YES   |
+----------------------+-------+
1 row in set (0.00 sec)

 

2、加载插件

因用户需执行INSTALL PLUGIN, SET GLOBAL, STOP SLAVE和START SLAVE操作,所以用户需有SUPER权限。

主:

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

从:

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

查看插件是否加载成功

方法1

mysql> show plugins;

rpl_semi_sync_master       | ACTIVE   | REPLICATION        | semisync_master.so | GPL

方法2

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';

+----------------------+---------------+

| PLUGIN_NAME          | PLUGIN_STATUS |

+----------------------+---------------+

| rpl_semi_sync_master | ACTIVE        |

+----------------------+---------------+

1 row in set (0.00 sec)

4、启动半同步复制

在安装完插件后,半同步复制默认是关闭的,这时需设置参数来开启半同步

主:

mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;

从:

mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;

注意:初次加载插件后,MySQL会将该插件记录到系统表mysql.plugin中,下次启动时系统会自动加载该插件。

在my.cnf配置文件里加入以下配置

主:

#semi_sync

plugin-load=rpl_semi_sync_master=semisync_master.so

rpl_semi_sync_master_enabled=1

从:

#semi_sync

plugin-load=rpl_semi_sync_slave=semisync_slave.so

rpl_semi_sync_slave_enabled=1

在有的高可用架构下,master和slave需同时启动,以便在切换后能继续使用半同步复制

plugin-load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
rpl-semi-sync-master-enabled = 1
rpl-semi-sync-slave-enabled = 1

 

5、重启从库IO线程

mysql> STOP SLAVE IO_THREAD;
mysql> START SLAVE IO_THREAD;

 

如果没有重启,则默认还是异步复制,重启后,slave会在master上注册为半同步复制的slave角色。

此时从库半同步模式正式开启

mysql> show status like '%semi_sync%';

+----------------------------+-------+

| Variable_name              | Value |

+----------------------------+-------+

| Rpl_semi_sync_slave_status | ON    |

+----------------------------+-------+

1 row in set (0.00 sec)

这时候,主的error.log中会打印如下信息:

2016-08-05T10:03:40.104327Z 5 [Note] While initializing dump thread for slave with UUID <ce9aaf22-5af6-11e6-850b-000c2988bad2>, found a zombie dump thread with the same UUID. Master is killing the zombie dump thread(4).

2016-08-05T10:03:40.111175Z 4 [Note] Stop asynchronous binlog_dump to slave (server_id: 2)

2016-08-05T10:03:40.119037Z 5 [Note] Start binlog_dump to master_thread_id(5) slave_server(2), pos(mysql-bin.000003, 621)

2016-08-05T10:03:40.119099Z 5 [Note] Start semi-sync binlog_dump to slave (server_id: 2), pos(mysql-bin.000003, 621)

6、查看半同步是否在运行

主库

mysql> show status like 'Rpl_semi_sync_master_status';

+-----------------------------+-------+

| Variable_name | Value |

+-----------------------------+-------+

| Rpl_semi_sync_master_status | ON    |

+-----------------------------+-------+

1 row in set (0.00 sec)

从库

mysql> show status like 'Rpl_semi_sync_slave_status';

+----------------------------+-------+

| Variable_name | Value |

+----------------------------+-------+

| Rpl_semi_sync_slave_status | ON    |

+----------------------------+-------+

1 row in set (0.20 sec)

这两个变量常用来监控主从是否运行在半同步复制模式下。

至此,MySQL半同步复制搭建完毕~~~

四、总结

事实上,半同步复制并不是严格意义上的半同步复制

当半同步复制发生超时时(由rpl_semi_sync_master_timeout参数控制,单位是毫秒,默认为10000,即10s),会暂时关闭半同步复制,转而使用异步复制。当master dump线程发送完一个事务的所有事件之后,如果在rpl_semi_sync_master_timeout内,收到了从库的响应,则主从又重新恢复为半同步复制。

该验证分为三个阶段

  1. 在Slave执行stop slave之前,主的insert操作很快就能返回。
  2. 在Slave执行stop slave后,主的insert操作需要10.01s才返回,而这与rpl_semi_sync_master_timeout参数的时间相吻合。

这时,查看两个状态的值,均为“OFF”了。

同时,主的error.log中打印如下信息:

2016-08-05T11:51:49.855452Z 6 [Warning] Timeout waiting for reply of binlog (file: mysql-bin.000003, pos: 1447), semi-sync up to file mysql-bin.000003, position 1196.

2016-08-05T11:51:49.855742Z 6 [Note] Semi-sync replication switched OFF.

3. 在Slave执行start slave后,主的insert操作很快就能返回,此时,两个状态的值也变为“ON”了。

同时,主的error.log中会打印如下信息:

2016-08-05T11:52:40.477098Z 7 [Note] Start binlog_dump to master_thread_id(7) slave_server(2), pos(mysql-bin.000003, 1196)

2016-08-05T11:52:40.477168Z 7 [Note] Start semi-sync binlog_dump to slave (server_id: 2), pos(mysql-bin.000003, 1196)

2016-08-05T11:52:40.523475Z 0 [Note] Semi-sync replication switched ON at (mysql-bin.000003, 1447)

小结

1. 在一主多从的架构中,如果要开启半同步复制,并不要求所有的从都是半同步复制。

2. MySQL 5.7极大的提升了半同步复制的性能。

5.6版本的半同步复制,dump thread 承担了两份不同且又十分频繁的任务:传送binlog 给slave ,还需要等待slave反馈信息,而且这两个任务是串行的,dump thread 必须等待 slave 返回之后才会传送下一个 events 事务。dump thread 已然成为整个半同步提高性能的瓶颈。在高并发业务场景下,这样的机制会影响数据库整体的TPS 。

5.7版本的半同步复制中,独立出一个 ack collector thread ,专门用于接收slave 的反馈信息。这样master 上有两个线程独立工作,可以同时发送binlog 到slave ,和接收slave的反馈。

转载于:https://my.oschina.net/u/3478888/blog/3002850

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值