IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [转][转] MySQL 5.5+ 主从同步 Semisync Replication

    heiyeshuwu发表于 2016-09-06 00:36:04
    love 0


    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 会提示:
        
    1. 140523 22:26:00 [Warning] Timeout waiting for reply of binlog (file: mysql-bin.000002, pos: 465893519), semi-sync up to file , position 0.
    2. 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 并且增强了功能。

    1. 支持发送binlog和接受ack的异步化;
    2. 支持在事务commit前等待ACK;
    3. 在server层判断备库是否要求半同步以减少Plugin锁冲突;
    4. 解除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/







沪ICP备19023445号-2号
友情链接