MySQL 5.5+ 主从同步 Semisync Replication
Posted 代码与远方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL 5.5+ 主从同步 Semisync Replication相关的知识,希望对你有一定的参考价值。
mysql5.5 semi-sync安装维护
mysql5.5 semi-sync replication 安装维护
MySQL的replication协议是异步的,虽然异步效率、性能很好,但是却无法保证主从数据一致性(如果master crash,已经commit的事务不会被传送到任何的slave上),从mysql5.5之后,mysql为了保证主从库数据一致性,引进了semi-sync功能,semi-sync意思是MASTER只需要接收到其中一台SLAVE的返回信息,就会commit;否则需等待直至切换成异步再提交。
优点:
当事务返回客户端成功后,则日志一定在至少两台主机上存在。
MySQL的Semi-sync适合小事务,且两台主机的延迟又较小,则Semi-sync可以实现在性能很小损失的情况下的零数据丢失。
缺点:
完成单个事务增加了额外的等待延迟,延迟的大小取决于网络的好坏。
Semi-sync不是分布式事务,主库会在自己完成事务后,等待备库接收事务日志(网易已经修改源码,使其在同一事务里)
备库Crash时,主库会在某次等待超时后,关闭Semi-sync的特性,降级为普通的异步复制,这种情况比较简单。
主库Crash后,那么可能存在一些事务已经在主库Commit,但是还没有传给任何备库,我们姑且称这类事务为"墙头事务"。"墙头事务"都是没有返回给客户端的,所以发起事务的客户端并不知道这个事务是否已经完成。这时,如果客户端不做切换,只是等Crash的主库恢复后,继续在主库进行操作,客户端会发现前面的"墙头事务"都已经完成,可以继续进行后续的业务处理;另一种情况,如果客户端Failover到备库上,客户端会发现前面的“墙头事务”都没有成功,则需要重新做这些事务,然后继续进行后续的业务处理。
安装
在主库安装semisync_master插件:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; //linux
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.dll'; //windows
在备库安装semisync_slave插件
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; //linux
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';//windows
在初次安装插件后,MySQL会将该插件记录到系统表mysql.plugin中,下次启动时系统则会自动加载该插件了,无需再次执行上面的命令。
简要安装如下
Master端的安装过程
1.INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
2.SHOW VARIABLES LIKE 'rpl_semi_sync_master_enabled' 值为ON,表示开启;否则检查失败原因
3.SET GLOBAL rpl_semi_sync_master_timeout=100000(利于观察);
4.SET GLOBAL rpl_semi_sync_master_wait_no_slave=1(是默认值,表示即使没有SLAVE也会等待过期时间结束)
Slave端的安装过程
1.INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
2.SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled' 值为ON,表示开启;否则失败检查原因
如果要启用半同步功能,在主备库的配置文件my.cnf还需要新增如下记录来打开semi-sync。
主库上,新增如下参数:
$vi my.cnf
...
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000
...
备库上新增:
$vi my.cnf
...
rpl_semi_sync_slave_enabled=1
...
如果考虑主备切换,就需要两个插件在master/slave上都安装,在配置文件my.cnf主备参数都需要添加
主备在启动后,且slave线程开始dump主库的日志后,Semi-sync Replication就会开启,上面的配置(rpl_semi_sync_master_timeout=1000)表示主库在某
次事务中,如果等待时间超过1000毫秒,那么则降级为普通模式,不再等待备库。如果主库再次探测到,备库恢复了,则会自动再次回到Semi-sync状态。
主备库上的参数
mysql> show variables like '%rpl_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_no_slave | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+------------------------------------+-------+
7 rows in set (0.00 sec)
从库上参数:
mysql> show variables like '%rpl_semi%';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+------------------------------------+-------+
6 rows in set (0.00 sec)
mysql>
如果在master上安装两个插件,master的参数如下(slave也一样):
mysql> show variables like '%rpl_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_no_slave | ON |
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+------------------------------------+-------+
6 rows in set (0.00 sec)
mysql>
参数说明:
rpl_semi_sync_master_timeout=1000 :表示主库在某次事务中,如果等待时间超过1000毫秒,那么则降级为普通模式,不再等待备库。
如果主库再次探测到,备库恢复了,则会自动再次回到Semi-sync状态,在测试时,可以设置大些,利于观察
rpl_semi_sync_master_wait_no_slave=1:表示即使没有SLAVE也会等待过期时间结束,是默认值,
这两个变量可以在线设置,但如果不写在my.cnf中,数据库重启参数就恢复默认值了
SET GLOBAL rpl_semi_sync_master_timeout=100000
SET GLOBAL rpl_semi_sync_master_wait_no_slave=1
验证master/slave是否启用semi-sync
检查master端semi-sync安装之后是否启用(rpl_semi_sync_master_enabled如果值为ON,表示开启;否则检查失败原因)
mysql> show variables like '%rpl_semi_sync_master_enabled%';
+------------------------------+-------+
| Variable_name | Value |
+------------------------------+-------+
| rpl_semi_sync_master_enabled | ON |
+------------------------------+-------+
1 row in set (0.00 sec)
检查slave端semi-sync安装之后是否启用(rpl_semi_sync_slave_enabled如果值为ON,表示开启;否则检查失败原因)
mysql> show variables like '%rpl_semi_sync_slave_enabled%';
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
+-----------------------------+-------+
1 row in set (0.00 sec)
mysql>
查看master/slave的semi-sync运行状态
在slave上查看semi-sync是否开启
mysql> show status like '%rpl_semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+--------------------------------------------+-------+
15 rows in set (0.00 sec)
mysql>
在master上查看semi-sync是否开启
mysql> show status like '%rpl_semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 2 | #有多少个Semi-sync的备库
| Rpl_semi_sync_master_net_avg_wait_time | 1209 | #事务提交后,等待备库响应的平均时间
| Rpl_semi_sync_master_net_wait_time | 213811529 | #等待网络响应的总次数
| Rpl_semi_sync_master_net_waits | 176714 | #总的网络等待时间
| Rpl_semi_sync_master_no_times | 0 | #一共有几次从Semi-sync跌回普通状态
| Rpl_semi_sync_master_no_tx | 0 | #备库未及时响应的事务数
| Rpl_semi_sync_master_status | ON | #主库上Semi-sync是否正常开启
| Rpl_semi_sync_master_timefunc_failures | 0 | #时间函数未正常工作的次数
| Rpl_semi_sync_master_tx_avg_wait_time | 1618 | #开启Semi-sync,事务返回需要等待的平均时间
| Rpl_semi_sync_master_tx_wait_time | 156225399 | #事务等待备库响应的总时间
| Rpl_semi_sync_master_tx_waits | 96501 | #事务等待备库响应的总次数
| Rpl_semi_sync_master_wait_pos_backtraverse | 1006 | #改变当前等待最小二进制日志的次数
| Rpl_semi_sync_master_wait_sessions | 0 | #当前有几个线程在等备库响应
| Rpl_semi_sync_master_yes_tx | 92171 | #Semi-sync模式下,成功的事务数
+--------------------------------------------+-------+
15 rows in set (0.00 sec)
mysql>
master状态参数说明
Rpl_semi_sync_master_tx_avg_wait_time:事务因开启Semi_sync,平均需要额外等待的时间
Rpl_semi_sync_master_net_avg_wait_time:事务进入等待队列后,网络平均等待时间
依据上面两个状态值可以知道,Semi-sync的网络消耗有多大,给某个事务带来的额外的消耗有多大。
Rpl_semi_sync_master_status: 则表示当前Semi-sync是否正常工作。
Rpl_semi_sync_master_no_times:表示可以知道一段时间内,Semi-sync是否有超时失败过,该计数器则记录了这样的失败次数。
参考:
http://www.orczhou.com/index.php/2011/06/mysql-5-5-semi-sync-replication-setup-config/
http://www.mysqlops.com/2011/10/24/mysql-semi-replicatio.html
http://code.google.com/p/google-mysql-tools/wiki/SemiSyncReplication
http://www.orczhou.com/index.php/2011/07/why-and-how-mysql-5-5-semi-sync-replication/
来源:http://blog.csdn.NET/wyzxg/article/details/8487953
【MySQL】Semisynchronous Replication 概述
前言
MySQL 5.5版本之前默认的复制是异步(Asynchronous )模式的, MySQL 5.5 以plugins的方式提供了Semisynchronous Replication 模式。在介绍 semi sync 之前,我们先了解:半同步 Asynchronous 和 同步 Synchronous 。
异步复制模式
主库将已经提交的事务event 写入binlog后,即返回成功给app,该模式下并不保证任何已经提交的事务会传递到任何slave并被成功应用。
全同步复制模式。
当主库提交一个事务 event,主库会等待该事务被传递到所有的slave上,且所有slave applay 该事务/event 通知主库之后,才会返回回话,事务已经成功。
从定义中可以看出 异步模式不能保证数据的安全性,因为它不等待主库提交的事务在slave 上落盘,而全同步模式 由于要等待所有的slave 确认已提交事务成功被应用,如此则会带来事务处理上的延时。semi sync 则取了一个比较折中的方式,确保已提交的事务必须存在于至少两个机器(主库和任一备库),立即返回给客户端 事务成功。
一 Semisynchronous Replication 定义
Semisynchronous Replication模式下,在主库上提交一个事务/event,它会等待至少一个slave通知主库,slave 已经接收到传递过来的events并写入relay log,才返回给回话层 写入成功,或者直到传送日志发生超时。
二 优缺点
优点:当事务返回成功给客户端时,则事务至少在两台机器上存在,增强数据安全性。相比异步模式和全同步模式,是一种折中。
缺点:半同步的确会对数据库性能有一定影响,因为事务的提交必须等待slave 反馈。性能损耗取决于tcp/IP 网络传输时间,也即传输已提交事务和等待slave 反馈已经接收事务的时间。
三 MySQL 半同步的特性
1 当slave 连接主库时,它会告知主库它是不是semi sync 模式。
2 如果主库启用了semi sync模式,且至少一个slave 也启用了semi sync模式,一个在主库操作事务的进程在事务提交之后,且至少一个slave 通知主库成功接收所有事务之前,该进程会处于blocks 等待状态或者直到超时发生。
3 当且仅当传递过来的events 传递到slave,被写入relay log,刷新到磁盘才会通知主库完成。
4 Semisynchronous replication 必须在主备两端都同时启用,否则任何一个未设置,主备之间的复制模式将转变为异步复制模式。
5 当所有slave 在(rpl_semi_sync_master_timeout的默认值)时间内未返回给主库成功接收event,主备之间就会变回原来的异步状态。
其中关于第二点 MySQL 5.7 已经做了优化,由ack Collector (Col) thread 等待备库的成功接收事务的通知,这点后续会做详细介绍--《5.7 Semisync replication 增强》。
四 异常处理
当备库Crash时,主库会在某次等待超时后,关闭Semi-sync的特性,降级为普通的异步复制,这种情况比较简单。
MySQL的 error.log 会提示:
140523 22:26:00 [Warning] Timeout waiting for reply of binlog (file: mysql-bin.000002, pos: 465893519), semi-sync up to file , position 0.
140523 22:26:00 [Note] Semi-sync replication switched OFF.
比较难以处理的情况是:当主机/主库Crash时,可能存在一些事务已经在主库提交,但是还没有来的及传给任何备库,也即这些事务都是没有返回给客户端的,所以发起事务的客户端并不知道这个事务是否已经完成--"墙头事务"。这时,如果客户端不做切换,只是等Crash的主库恢复后,继续在主库进行操作,客户端会发现前面的"墙头事务"都已经完成,可以继续进行后续的业务处理;另一种情况,如果客户端Failover到备库上,客户端会发现前面的“墙头事务”都没有成功,则需要重新做这些事务,然后继续进行后续的业务处理,其实此时主备是不一致的,需要通过主备数据校验来检查哪一个库是正确的,然后进行修复。
五 小结
总之相比于MySQL 5.5 版本之前的异步复制模式 semi sync 已经有了很大的进步,增强了数据的安全性,以安全换一定的性能损耗还是可以接受的。后续会介绍如何安装和使用semi sync。
六 推荐文章
[1] Semisynchronous replication
[2] Semisync separate acks collector
[3] MySQL半同步Semi-sync原理介绍
[4] SemiSync Replication Design
来源:http://blog.itpub.net/22664653/viewspace-1168839/
【MySQL】5.7版本 Semisync Replication 增强
一 前言
前文 介绍了5.5/5.6 版本的MySQL semi sync 基础原理和配置,随着MySQL 5.7 的发布,新版本的MySQL修复了semi sync 的一些bug 并且增强了功能。
支持发送binlog和接受ack的异步化;
支持在事务commit前等待ACK;
在server层判断备库是否要求半同步以减少Plugin锁冲突;
解除binlog dump线程和lock_log的冲突等等。
本文重点分析 第1,2个改进项,因为原来的模式的确会影响系统的tps,新的异步模式可以提高半同步模式下的系统事务处理能力。
二 优化
1 支持发送binlog和接受ack的异步化
通过前面的介绍,我们知道Semisynchronous Replication模式下,app在主库上提交一个事务/event,MySQL将每个事务写入binary并且同步到到slave ,master会等待至少一个slave通知:slave 已经接收到传过来的events并写入relay log,才返回给回话层 写入成功,或者直到传送日志发生超时,系统自动将为异步复制模式。
整体流程的逻辑图
5.5 版本semi sync 设计的缺点:
从原理以及上图来看,旧版本的semi sync 受限于dump thread ,原因是dump thread 承担了两份不同且又十分频繁的任务:传送binlog 给slave ,还需要等待slave反馈信息,而且这两个任务是串行的,dump thread 必须等待 slave 返回之后才会传送下一个 events 事务。dump thread 已然成为整个半同步提高性能的瓶颈在高并发业务场景下,这样的机制会影响数据库整体的TPS .
为了解决上述问题,在5.7.4版本的semi sync 框架中,独立出一个 ack collector thread ,专门用于接收slave 的反馈信息。这样master 上有两个进程独立工作,可以同时发送binlog 到slave ,和接收slave的反馈。整体流程的逻辑图
大体的实现思路是:
备库IO线程使用TCP协议和主库交互,读写socket可以同时进行,在开启主库semisync时,启动一个后台线程,使用select监听备库连接socket;
dump线程不再等待备库ACK;在ack reciver线程等待ACK时,dump线程还能继续发送下一组group commit的binlog,进而提升TPS.
2 支持在事务commit前等待ACK;
新版本的semi sync 增加了rpl_semi_sync_master_wait_point参数 来控制半同步模式下 主库在返回给会话事务成功之前提交事务的方式。
该参数有两个值:
AFTER_SYNC (默认值):master 将每个事务写入binlog ,传递到slave,并且刷新到磁盘。master等待slave 反馈接收到事务并刷新到磁盘。一旦接到slave反馈,master在主库提交事务并且返回结果给会话。 在AFTER_SYNC模式下,所有的客户端在同一时刻查看已经提交的数据。假如发生主库crash,所有在主库上已经提交的事务已经同步到slave并记录到relay log。此时切换到从库,可以保障最小的数据损失。
AFTER_COMMIT: master 将每个事务写入binlog ,传递到slave 刷新到磁盘(relay log),然后在主库提交事务。master在提交事务后等待slave 反馈接收到事务并刷新到磁盘。一旦接到slave反馈,master将结果反馈给客户端。
在AFTER_COMMIT模式下,如果slave 没有应用日志,此时master crash,系统failover到slave,app将发现数据出现不一致,在master提交而slave 没有应用。
三 推荐阅读
注:最后三个来自于MySQL replication 开发小组的blog,需要翻墙,请自备梯子。
[1] 5.7 Semisynchronous Replication
[2] loss-less-semi-synchronous-replication
MySQL 5.7 修改了半同步中主库提交的事务的顺序,after sync 模式避免了幻读发生。
[3] enforced-semi-synchronous-replication
MySQL 5.7 半同步增强,增加 rpl_semi_sync_master_wait_slave_count 参数控制主库接收多少个slave 写事务成功反馈 才返回 成功给客户端 。
[4] faster-semisync-replication
修改原来有dump thread 发送event和接收slave ack 模式,独立出 单独 接收slave 返回 ack的进程,提高半同步模式的tps 。
来源:http://blog.itpub.Net/22664653/viewspace-1183057/
以上是关于MySQL 5.5+ 主从同步 Semisync Replication的主要内容,如果未能解决你的问题,请参考以下文章