1.半同步复制
半同步复制官方手册:https://dev.mysql.com/doc/refman/5.7/en/replication-semisync.html
默认情况下,MySQL的复制是异步的,master将新生成的binlog发送给各slave后,无需等待slave的ack回复(slave将接收到的binlog写进relay log后才会回复ack),直接就认为这次DDL/DML成功了。
半同步复制(semi-synchronous replication)是指master在将新生成的binlog发送给各slave时,只需等待一个(默认)slave返回的ack信息就返回成功。
MySQL 5.7对半同步复制作了大改进,新增了一个master线程。在MySQL 5.7以前,master上的binlog dump线程负责两件事:dump日志给slave的io_thread;接收来自slave的ack消息。它们是串行方式工作的。在MySQL 5.7中,新增了一个专门负责接受ack消息的线程ack collector thread。这样master上有两个线程独立工作,可以同时发送binlog到slave和接收slave的ack。
还新增了几个变量,其中最重要的是 rpl_semi_sync_master_wait_point ,它使得MySQL半同步复制有两种工作模型。解释如下。
2.半同步复制的两种类型
从MySQL 5.7.2开始,MySQL支持两种类型的半同步复制。这两种类型由变量 rpl_semi_sync_master_wait_point (MySQL 5.7.2之前没有该变量)控制,它有两种值:AFTER_SYNC和AFTER_COMMIT。在MySQL 5.7.2之后,默认值为AFTER_SYNC,在此版本之前,等价的类型为AFTER_COMMIT。
这个变量控制的是master何时提交、何时接收ack以及何时回复成功信息给客户端的时间点。
AFTER_SYNC
模式:master将新的事务写进binlog(buffer),然后发送给slave,再sync到自己的binlog file(disk)。之后才允许接收slave的ack回复,接收到ack之后才会提交事务,并返回成功信息给客户端。AFTER_COMMIT
模式:master将新的事务写进binlog(buffer),然后发送给slave,再sync到自己的binlog file(disk),然后直接提交事务。之后才允许接收slave的ack回复,然后再返回成功信息给客户端。
画图理解就很清晰。
再来分析下这两种模式的优缺点。
AFTER_SYNC
:对于所有客户端来说,它们看到的数据是一样的,因为它们看到的数据都是在接收到slave的ack后提交后的数据。
这种模式下,如果master突然故障,不会丢失数据,因为所有成功的事务都已经写进slave的relay log中了,slave的数据是最新的。
AFTER_COMMIT
:不同客户端看到的数据可能是不一样的。对于发起事务请求的那个客户端,它只有在master提交事务且收到slave的ack后才能看到提交的数据。但对于那些非本次事务的请求客户端,它们在master提交后就能看到提交后的数据,这时候master可能还没收到slave的ack。
如果master收到ack回复前,slave和master都故障了,那么将丢失这个事务中的数据。
在MySQL 5.7.2之前,等价的模式是 AFTER_COMMIT ,在此版本之后,默认的模式为 AFTER_SYNC ,该模式能最大程度地保证数据安全性,且性能上并不比 AFTER_COMMIT 差。
3.半同步复制插件介绍
MySQL的半同步是通过加载google为MySQL提供的半同步插件 semisync_master.so 和 semisync_slave.so 来实现的。其中前者是master上需要安装的插件,后者是slave上需要安装的插件。
MySQL的插件位置默认存放在$basedir/lib/plugin
目录下。例如,yum安装的mysql-server,插件目录为/usr/lib64/mysql/plugin。
[root@xuexi ~]# find / -type f -name "semisync*" /usr/lib64/mysql/plugin/debug/semisync_master.so/usr/lib64/mysql/plugin/debug/semisync_slave.so/usr/lib64/mysql/plugin/semisync_master.so/usr/lib64/mysql/plugin/semisync_slave.so
因为要加载插件,所以应该保证需要加载插件的MySQL的全局变量 have_dynamic_loading 已经设置为YES(默认值就是YES),否则无法动态加载插件。
mysql> select @@global.have_dynamic_loading; +-------------------------------+| @@global.have_dynamic_loading | +-------------------------------+| YES | +-------------------------------+
3.1 MySQL中安装插件的方式
安装插件有两种方式:1.在mysql环境中使用INSTALL PLUGIN
语句临时安装;2.在配置文件中配置永久生效。
INSTALL安装插件的语法为:
Syntax:INSTALL PLUGIN plugin_name SONAME 'shared_library_name'UNINSTALL PLUGIN plugin_name
例如,使用INSTALL语句在master上安装 semisync_master.so 插件。
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
配置文件中加载插件的方式为:
[mysqld]plugin-load='plugin_name=shared_library_name'
例如,配置文件中加载semisync_master.so
插件。
[mysqld]plugin-load="rpl_semi_sync_master=sermisync_master.so"
如果需要加载多个插件,则插件之间使用分号分隔。例如,在本节的slave1既是slave,又是master,需要同时安装两个半同步插件。
[mysqld]plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_sync_slave=semisync_slave.so"
安装插件后,应该使用show plugins
来查看插件是否真的激活。
mysql> show plugins; +----------------------+--------+-------------+--------------------+---------+ | Name | Status | Type | Library | License | +----------------------+--------+-------------+--------------------+---------+ ...... | rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL | +----------------------+--------+-------------+--------------------+---------+
或者查看information_schema.plugins
表获取更详细的信息。
mysql> select * from information_schema.plugins where plugin_name like "%semi%"\G *************************** 1. row *************************** PLUGIN_NAME: rpl_semi_sync_master PLUGIN_VERSION: 1.0 PLUGIN_STATUS: ACTIVE PLUGIN_TYPE: REPLICATION PLUGIN_TYPE_VERSION: 4.0 PLUGIN_LIBRARY: semisync_master.soPLUGIN_LIBRARY_VERSION: 1.7 PLUGIN_AUTHOR: He Zhenxing PLUGIN_DESCRIPTION: Semi-synchronous replication master PLUGIN_LICENSE: GPL LOAD_OPTION: ON1 row in set (0.00 sec)
插件装载完成后,半同步功能还未开启,需要手动设置它们启动,或者写入配置文件永久生效。
# 开启master的半同步mysql> set @@global.rpl_semi_sync_master_enabled=1;# 开启slave半同步mysql> set @@globale.rpl_semi_sync_slave_enabled=1;
或者配合插件加载选项一起写进配置文件永久开启半同步功能。
[mysqld]rpl_semi_sync_master_enabled=1[mysqld]rpl_semi_sync_slave_enabled=1
3.2 半同步插件相关的变量
安装了 semisync_master.so 和 semisync_slave.so 后,这两个插件分别提供了几个变量。
mysql> show global variables like "%semi%"; +-------------------------------------------+------------+| Variable_name | Value | +-------------------------------------------+------------+| rpl_semi_sync_master_enabled | OFF | | rpl_semi_sync_master_timeout | 10000 | | 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 | | rpl_semi_sync_slave_enabled | OFF | | rpl_semi_sync_slave_trace_level | 32 | +-------------------------------------------+------------+
下面还多给了两个和半同步相关的状态变量的解释,可以通过show status like %semi%;
查看它们。
master相关的变量:
①.
Rpl_semi_sync_master_clients
:(状态变量)master所拥有的半同步复制slave的主机数量。②.
Rpl_semi_sync_master_status
:(状态变量)master当前是否以半同步复制状态工作(ON),OFF表示降级为了异步复制。③.
rpl_semi_sync_master_enabled
:master上是否启用了半同步复制。④.
rpl_semi_sync_master_timeout
:等待slave的ack回复的超时时间,默认为10秒。⑤.
rpl_semi_sync_master_trace_level
:半同步复制时master的调试级别。⑥.
rpl_semi_sync_master_wait_for_slave_count
:master在超时时间内需要收到多少个ack回复才认为此次DML成功,否则就降级为异步复制。该变量在MySQL5.7.3才提供,在此之前的版本都默认为收到1个ack则确认成功,且不可更改。MySQL 5.7.3之后该变量的默认值也是1。⑦.
rpl_semi_sync_master_wait_no_slave
:值为ON(默认)或者OFF。ON表示master在超时时间内如果未收到指定数量的ack消息,则会一直等待下去直到收满ack,即一直采用半同步复制方式,不会降级;OFF表示如果在超时时间内未收到指定数量的ack,则超时时间一过立即降级为异步复制。更官方的解释是:当设置为ON时,即使状态变量Rpl_semi_sync_master_clients中的值小于rpl_semi_sync_master_wait_for_slave_count,Rpl_semi_sync_master_status依旧为ON;当设置为OFF时,如果clients的值小于count的值,则Rpl_semi_sync_master_status立即变为OFF。通俗地讲,就是在超时时间内,如果slave宕机的数量超过了应该要收到的ack数量,master是否降级为异步复制。
该变量在MySQL 5.7.3之前似乎没有效果,因为默认设置为ON时,超时时间内收不到任何ack时仍然会降级为异步复制。
⑧.
rpl_semi_sync_master_wait_point
:控制master上commit、接收ack、返回消息给客户端的时间点。值为 AFTER_SYNC 和 AFTER_COMMIT ,该选项是MySQL5.7.2后引入的,默认值为 AFTER_SYNC ,在此版本之前,等价于使用了 AFTER_COMMIT 模式。关于这两种模式,见前文对两种半同步类型的分析。
slave相关的变量:
①.
rpl_semi_sync_slave_enabled
:slave是否开启半同步复制。②.
rpl_semi_sync_slave_trace_level
:slave的调试级别。
4.配置半同步复制
需要注意的是,"半同步"是同步/异步类型的一种情况,既可以实现半同步的传统复制,也可以实现半同步的GTID复制。其实半同步复制是基于异步复制的,它是在异步复制的基础上通过加载半同步插件的形式来实现半同步性的。
此处以全新的环境进行配置,方便各位道友"依葫芦画瓢"。
本文实现如下拓扑图所示的半同步传统复制。如果要实现半同步GTID复制,也只是在gtid复制的基础上改改配置文件而已。
具体环境:
称呼 | 主机IP | MySQL版本 | OS | 角色(master/slave) | 数据库状态 |
---|---|---|---|---|---|
master | 192.168.100.21 | MySQL 5.7.22 | CentOS 7.2 | master | 全新实例 |
salve1 | 192.168.100.22 | MySQL 5.7.22 | CentOS 7.2 | semi_slave for master semi_master for other slaves | 全新实例 |
slave2 | 192.168.100.23 | MySQL 5.7.22 | CentOS 7.2 | semi_slave for slave1 | 全新实例 |
slave3 | 192.168.100.24 | MySQL 5.7.22 | CentOS 7.2 | semi_slave for slave1 | 全新实例 |
因为都是全新的实例环境,所以无需考虑基准数据和binlog坐标的问题。如果开始测试前,已经在master上做了一些操作,或者创建了一些新数据,那么请将master上的数据恢复到各slave上,并获取master binlog的坐标,具体操作方法可参见前文:将slave恢复到master指定的坐标。
4.1 半同步复制的配置文件
首先提供各MySQL Server的配置文件。
以下是master的配置文件。
[mysqld]datadir=/datasocket=/data/mysql.socklog-error=/data/error.logpid-file=/data/mysqld.pidlog-bin=/data/master-binsync-binlog=1server-id=100plugin-load="rpl_semi_sync_master=semisync_master.so"rpl_semi_sync_master_enabled=1
以下是slave1的配置文件,注意slave1同时还充当着slave2和slave3的master的角色。
[mysqld]datadir=/datasocket=/data/mysql.socklog-error=/data/error.logpid-file=/data/mysqld.pidlog-bin=/data/master-binsync-binlog=1server-id=110relay-log=/data/slave-binlog-slave-updatesplugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"rpl_semi_sync_slave_enabled=1rpl_semi_sync_master_enabled=1
以下是slave2和slave3的配置文件,它们配置文件除了server-id外都一致。
[mysqld]datadir=/datasocket=/data/mysql.socklog-error=/data/error.logpid-file=/data/mysqld.pidserver-id=120 # slave3的server-id=130relay-log=/data/slave-binplugin-load="rpl_semi_sync_slave=semisync_slave.so"rpl_semi_sync_slave_enabled=1read-only=on
4.2 启动复制线程
现在master上创建一个专门用于复制的用户。
mysql> create user repl@'192.168.100.%' identified by 'P@ssword1!'; mysql> grant replication slave on *.* to repl@'192.168.100.%';
因为master和所有的slave都是全新的实例,所以slave上指定的binlog坐标可以从任意位置开始。不过刚才master上创建了一个用户,也会写binlog,所以建议还是从master的第一个binlog的position=4开始。
以下是slave1上的change master to
参数:
mysql> change master to master_host='192.168.100.21', master_port=3306, master_user='repl', master_password='P@ssword1!', master_log_file='master-bin.000001', master_log_pos=4;
以下是slave2和slave3的change master to
参数:
mysql> change master to master_host='192.168.100.22', master_port=3306, master_user='repl', master_password='P@ssword1!', master_log_file='master-bin.000001', master_log_pos=4;
启动各slave上的两个SQL线程。
mysql> start slave;
一切就绪后,剩下的事情就是测试。在master上对数据做一番修改,然后查看是否会同步到slave1、slave2、slave3上。
5.半同步复制的状态信息
共同學(xué)習(xí),寫下你的評(píng)論
評(píng)論加載中...
作者其他優(yōu)質(zhì)文章