MySQL是一个RDBMS(关系型数据库管理系统),由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。由于其体积小、速度快、拥有成本低,尤其是开放源码这一特点,广受各大企业欢迎,包括腾讯,阿里,百度,网易,Google,FaceBook等互联网巨头企业。

随着互联网的高速发展,互联网服务可用性变得越发重要,数据容灾也随之成为各企业的关键任务。在数据容灾中,数据库集群如何处理数据一致性也成为了各企业需要解决的问题。特别在一些新兴的金融服务中,MySQL也逐渐成为其核心数据库,如何保证金钱的准确性则尤为重要。MySQL也从一开始的异步复制,到Google开发的半同步复制,到MySQL 5.7更新的lossless半同步复制,一直在优化集群的数据一致性问题。

虽然MySQL一直在优化数据的一致性问题,但问题依然存在,使得各大企业纷纷各自设计一套MySQL补丁来保证数据一致。腾讯数平的TDSQL,腾讯微信的PhxSQL,阿里的AliSQL,网易的InnoSQL等设计都是为了保证数据一致性。MySQL5.7发布的lossless半同步,虽然宣称zero loss,解决了5.6版本中有可能出现的data lost问题,但其数据一致性仍未完全解决。

MySQL半同步复制的问题

图1 MySql半同步流程

图1描述了MySQL的Binlog半同步过程。Wait ACK是半同步的关键步骤,Master把Binlog发给Slave之后,需要等待Slave的ACK。Master直到成功收到ACK之后,才执行Engine Commit把数据持久化到Storage。具体细节可参考:http://my-replication-life.blogspot.com/2013/09/loss-less-semi-synchronous-replication.html

MySQL启动时,Wait ACK过程会被跳过,导致Engine Commit会被直接执行。具体细节请参考:https://jira.mariadb.org/browse/MDEV-162

下面对MySQL的数据在Master和Slave之间是否能保证一致进行简单分析。讨论均基于各机器数据最终是否一致来展开。下面的分析只针对半同步复制,且假设半同步失败后不会退化成异步复制。

场景1:Master正常工作

Master的数据复制到Slave,Slave与Master保持数据一致。

场景2:Master Crash且不切换Master

场景2.1

Master已经收到ACK,并执行Engine Commit。Slave与Master保持数据一致。

场景2.2

Master处于Wait ACK阶段,存在PendingBinlog(未执行Engine Commit的Binlog)。

图2 Master重启时执行EngineCommit,并把Binlog重新复制给Slave

Master重启时执行EngineCommit。Slave重新连接Master,Binlog重新开始复制,随后Slave数据和Master一致。如图2。

因此,在MySql5.7的情况下,场景2.2能保证Master和Slave之间的数据一致性。但是在MySQL5.6及之前的版本,场景2.2是不能保证数据一致性的,具体请参考:http://my-replication-life.blogspot.com/2013/09/loss-less-semi-synchronous-replication.html

场景3:Master Crash且切换Master

场景3.1

旧Master Crash时,已经收到至少一台Slave的ACK并执行Engine Commit。

数据已复制到至少一台Slave,该Slave与旧Master的数据保持一致。

场景3.2

旧Master处于Wait ACK阶段时Crash,新Master被切换到了一台拥有最新Binlog的Slave。

场景3.2中,旧Master中的PendingBinlog存在两种场景。

场景3.2.1

旧Master Crash时Binlog发送失败,未复制给任何Slave。

图3 机器A重启Commit Transaction X。机器A/B数据不一致。

图4 机器B接收到事务X的重试请求(事务X’)且复制到机器A。

机器A/B数据可能不一致。

假设机器A为旧Master,执行事务X时,复制失败并Crash。随后机器B成为新Master。机器A重启时执行Engine Commit,事务X被Commit。此时机器A和机器B的数据一致性被破坏。两台机器上数据可能不一致。如图3,图4。

数据不一致的原因是机器A在重启时对PendingBinlog执行Engine Commit。在切换了Master的情况下,只能通过回滚PendingBinlog解决。

场景3.2.2

旧Master Crash时Binlog发送成功,但还未执行Engine Commit。

图6 机器A重启马上执行Engine Commit,数据一致

假设机器A为旧Master,执行事务X时在执行Commit前Crash,但机器B收到事务X。随后机器B成为新Master。

机器A重启时对PendingBinlog执行Engine Commit,执行成功后机器A的数据是机器B的子集。此时机器A可从机器B中拉取最新的数据。另外一台Slave机器C可以从这两台机器中任意拉取。

从图6可以看出,机器A在出现故障时,由于TransactionX已经复制给其中一台Slave和重启时立刻Commit Transaction X,使得该Slave和Master的数据能保证一致。

图7 两台机器出现故障,Master切换可能会丢失数据

上述讨论都是基于拥有最新数据的Slave和Master不能一起出现故障。当这两台机器一起出现故障时,进行Master切换则会造成数据丢失。如图7。

对于较小的集群(机器数目小于或者等于3),当出现两台机器一起发生故障时,可认为集群已无法提供服务(半同步复制无法工作)。

对于较大的集群(机器数目大于3),当出现两台机器一起发生故障,且无法得知该两台机器的数据状态时,该集群也无法提供服务(无法确认拥有最新数据的Slave是否包含在故障机器中)。因此,对于较大的集群,通常增加半同步复制等待ACK的数目,使得出现上述状况时,仍能进行Master切换(非故障机器中,存在拥有最新数据的机器)。

增加等待ACK的数目,解决了数据丢失的问题,但同时给数据回滚带来了难题。

图8

如图8。假设MySQL集群有5台机器,半同步复制需要等待2台Slave的ACK。机器A为旧Master,在执行Wait ACK阶段,机器B收到Binlog后,机器A和机器B同时Crash或者被隔离,导致Binlog复制失败。根据场景3.2.1的分析,当机器C成为Master后,机器A和机器B在恢复服务前需要对其进行数据回滚。但对Slave进行数据回滚较为困难。且若回滚失败,则会出现数据不一致。

对于较小的集群,回滚PendingBinlog比较容易实现。但对于较大的集群,回滚PendingBinlog本身就是一个未解决的难题。

MySQL的Master切换问题

Master如何切换同时也是MySQL容灾中的一个难题。

一个简单的Master切换步骤:

1. Pause旧Master

2. Start新Master

3. 更换MySQLClient的Master指向IP

存在以下几个问题:

1. 当Master被隔离时,如何将其变更为Slave

解决方法:可修改MySQL的代码,使用zookeeper等外部辅助服务来自动维护Master的状态,可解决Master被隔离后不能操作的问题。

2. 如何定位拥有最新Binlog数据的MySQL

解决方法:可以通过人工,或者使用外部工具来检测集群每台MySQL的数据。但当出现故障机器无法访问时,无法定位。

3. 如何进行数据回滚

解决方法:可以通过运维进行人工操作。

4. 如何同时更换MySQLClient的Master指向IP

同时更换所有MySQLClient的Master指向IP是一件不可能的事情,因为不可能同一时刻操作所有机器。

不能同时更换所有MySQLClient的Master指向IP,导致部分Client会向旧Master发送请求,即出现多个Master同时服务。在使用半同步复制的情况下,多台MySQL不能同时知道Master的去向,使得数据可能产生不一致的情况。

图9

图10

假设机器A是旧Master,机器B是新Master,机器C还没收到Master更换的通知仍然向机器A复制Binlog。User1在Master切换前已经连上机器A并持续写入数据。User2在Master切换后开始向机器B写入数据。由于机器A能把数据复制给机器C,机器B能把数据复制给机器A,因此机器A和机器B都能成功写入。如图9。

由于机器A和机器B同时写入数据,数据一致性无法保证。如图10。

总结

从上面分析来看,MySQL的半同步复制和Master切换都存在一些不足。数据复制存在回滚难题,Master切换存在多Master难题。只有解决了这两大难题,才能保证MySQL集群的数据一致性。

MySQL半同步复制的数据一致性探讨微信后台团队实践【转】的更多相关文章

  1. Mysql半同步复制模式说明及配置示例 - 运维小结

    MySQL主从复制包括异步模式.半同步模式.GTID模式以及多源复制模式,默认是异步模式 (如之前详细介绍的mysql主从复制).所谓异步模式指的是MySQL 主服务器上I/O thread 线程将二 ...

  2. mysql半同步复制跟无损半同步区别

    mysql半同步复制跟无损半同步复制的区别: 无损复制其实就是对semi sync增加了rpl_semi_sync_master_wait_point参数,来控制半同步模式下主库在返回给会话事务成功之 ...

  3. MySQL半同步复制

    从MySQL5.5开始,MySQL以插件的形式支持半同步复制.如何理解半同步呢?首先我们来看看异步,全同步的概念 异步复制(Asynchronous replication) MySQL默认的复制即是 ...

  4. 安装MySQL半同步复制

    一.简介 从MySQL5.5开始,MySQL以插件的形式支持半同步复制.如何理解半同步呢?首先我们来看看异步,全同步的概念 异步复制(Asynchronous replication) MySQL默认 ...

  5. MySQL半同步复制(5.5之后引入)

    半同步复制架构在主库提交一个事务后,commit完成即反馈客户端,无需等待推送binlog完成,如图: 半同步复制在主库完成一个事务后,需等待事务信息写入binlog日志并且至少有一个从库写入rela ...

  6. mysql半同步复制实现

    mysql半同步复制和异步复制的区别如上述架构图所看到的:在mysql异步复制的情况下.Mysql Master Server将自己的Binary Log通过复制线程传输出去以后,Mysql Mast ...

  7. MySQL半同步复制搭建

    默认情况下,MySQL 5.5/5.6/5.7和MariaDB 10.0/10.1的复制是异步的,异步复制可以提供最佳性能,主库把binlog日志发送给从库,这一动作就结束了,并不会验证从库是否接收完 ...

  8. (5.5)mysql高可用系列——MySQL半同步复制(实践)

    关键词,mysql半同步复制 [0]实验环境 操作系统:CentOS linux 7.5 数据库版本:5.7.24 数据库架构:主从复制,主库用于生产,从库用于数据容灾和主库备机,采用默认传统的异步复 ...

  9. MySQL半同步复制源码解析

    今天 DBA 同事问了一个问题,MySQL在半同步复制的场景下,当关闭从节点时使得从节点的数量 < rpl_semi_sync_master_wait_for_slave_count时,show ...

随机推荐

  1. Transform 位置 旋转

    using UnityEngine; using System.Collections; using Box2D.Dynamics; public class BodyGameObj : MonoBe ...

  2. Javaweb 第15天 web练习和分页技术

    第15天 web练习和分页技术 复习day14内容: 学习新技术的思路? 分析功能的思路? 使用queryRunner操作数据库的步骤? ResultSetHandler接口常用实现类(三个重点)? ...

  3. smarty模板设计

      一.什么是smarty? smarty是一个使用PHP写出来的模板PHP模板引擎,它提供了逻辑与外在内容的分离,简单的讲,目的就是要使用PHP程序员同美工分离,使用的程序员改变程序的逻辑内容不会影 ...

  4. 实验吧Web-天网管理系统

    笔记 == : 比较运算符号  不会检查条件式的表达式的类型 ===:  恒等计算符 , 同时检查表达式的值与类型.(会检查表达式类型,如bool) PHP序列化与反序列化serialize() 对输 ...

  5. 弹性布局EM的计算方法

    文章来源: http://www.w3cplus.com/css/px-to-em 总结: 1.浏览器默认的字体大小为16PX,即1em 2.EM可以指定小数点的后三位 3.元素自身没有设置字体大小, ...

  6. Linux入门(三)搭建服务器linux运行环境LAMP/LNMP

    本文内容主要根据慕课网教学视频整理,原链接http://www.imooc.com/learn/170 我用的linux系统是ubuntu 12.04 LTS  虚拟机是VMware Workstat ...

  7. 邮件发送 java

    package com.sun.mail; import java.io.File;import java.io.IOException;import java.io.UnsupportedEncod ...

  8. C/C++的静态库与动态库

    C/C++编程中相关文件后缀(以Linux系统下为例): .a:           静态库(archive) .c/.cpp:  C/C++源程序 .h/.hpp: C/C++源程序的头文件 .i: ...

  9. Mysql授权远程登录

    在命令行输入如下命令即可: Grant all privileges on *.* to ' with grant option; 再执行 flush privileges

  10. ubuntn安装五笔输入法

    1.首先要把原来的 ibus 卸载掉 sudo apt-get remove ibus 2.添加源 sudo add-apt-repository ppa:fcitx-t(www.111cn.net) ...