• MySQL MHA原理(一)

    MHA的存在意义及基本特性

    我们都知道MHA是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。下面是他作为高可用框架的一些基本特性。

    参数
    故障响应时间 0 - 30s
    服务器资源的利用率 很高,MHA是独立于MySQL集群本身的,只是保证了集群的高可用。不会因为架构的原因导致某个从库单纯的只作为备份而不提供服务。
    故障切换是否安全 MHA会在切换过程中尽可能的保证数据的一致性。
    维护成本和难度 是比较成熟且受欢迎的开源高可用框架,所以文档和网上的FAQ案例也相对来说比较完善。
    二次开发特性 可以按需调整故障检测和故障响应的方式,算是比较灵活了吧
    是否会产生脑裂等现象 不会

    MHA的限制条件

    1. 目前MHA主要支持一主多从的架构

    • 要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。
    • 默认情况下,MHA是不支持3层或多层复制架构的(Master1 -> Master2 -> Slave3), MHA可以恢复Master2,但是不能恢复Slave3,因为Master2,Slave3有不同的master,为了让MHA支持以上架构,可以参考如下配置:
    • 在配置文件中,只配置两层(master1 and master2)
    • 使用 “multi_tier_slave=1” 参数,然后设置所有hosts

    2. MySQL版本必须是5.0 或者高于 5.0

    3. 使用mysqlbinlog 5.1+ 支持MySQL5.1+

    • MHA使用mysqlbinlog来应用日志到目标slave上的
    • 如果MySQL master设置的是row格式,那么MySQL必须是大于等于5.1版本,因为5.0不支持row
    • mysqlbinlog版本可以这样被检测:

    • 如果你使用的是MySQL5.1,那么mysqlbinlog必须大于等于3.3
    • 如果mysqlbinlog的版本是3.2,而mysql的版本是5.1,那么mha manager会报错,且停止monitoring

    4. log-bin必须在候选master上开启

    • 如果当前slave没有设置log-bin,那么很显然它不能成为提升为new master
    • 如果没有任何机器设置了log-bin,那么mha会报错且停止failover

    5. binlog,relay-log 主从环境必须全部一致

    • 复制过滤规则(binlog-do-db, replicate-ignore-db 等等)必须全部一致

    6. 复制用户必须在候选master上要存在

    • 切换完成后,所有slave都必须执行change master 命令。在new master上复制用户必须有(REPLICATEION SLAVE权限)

    7. 使用purge_relay_logs来定期删除relay logs

    • 默认情况下,如果SQL线程执行完relay-log,relay logs就会被自动删除。但是这些relay-logs 也许还会用来恢复其他的slave,所以你需要关闭自动删除relay-logs的purge线程,然后自己阶段性的来删除如果是你自己来删的话,必须考虑repl 延迟问题,最好让slave删除relay log不要在同一时间点,假如需要恢复,那么这个时间点所有relay logs都被删除了就不好了。

    MHA 的基本结构

    从架构上来说,MHA分为如下两大部分:

    1. Node部分

    我们知道,MHA是基于MySQL Replication环境的,在该环境中,不管是Master角色,还是Slave角色,都称为Node,是被监控管理的对象节点。

    Node服务器上需要安装MHA Node包。

    2. Manager部分

    Manager为MHA架构中的管理者,建议部署在一台独立的服务器上,当然也可部署在某个Slave上,但该Slave永远不要被选择成为新的Master,否则故障切换后的MHA架构就失去了高可用性。Manager服务器需要安装MHA Manager包,并完善一个主配置文件。

    一个Manager可管理多套MySQL Replication环境(图片摘自网上)。

    yy

    MHA安装配置

    现在我有这样一套基于3306端口的主从复制结构,需要加上MHA的高可用:

    IP地址 角色 hostname server id 类型
    10.67.250.1 Master server1 1
    10.67.250.2 slave1 + Manager server2 2 只读
    10.67.250.3 slave2 (backup) server3 3 只读
    1. 在每台MHA集群服务器上安装依赖

    2. 在每台机器上安装MHA Node软件包

    推荐使用rpm的方式安装:

    也可以选择源码安装:

    Node工具包(这些工具通常由MHA Manager的脚本触发,无需人为操作)主要包括以下几个工具:

    3. 安装MHA Manager

    推荐使用rpm的安装方式:

    也可以使用源码方式安装:

    Manager工具包主要包括以下几个工具:

    如果你采用的是源码安装,那么安装完Manager后在安装目录底下存在一个 sample/scripts 目录,里面存在了一些功能性脚本:

    4. 配置前的准备工作

    首先需要做一些配置之前的准备工作:

    4.1 两台slave服务器设置read_only

    4.2 创建监控用户,用于MHA Manager管理其他数据库node节点

    4.3 实现三台服务器之间的SSH免密码登录

    详情可参考 http://www.foreverlakers.com/tag/ssh/ 

    注: 这里要注意,如果我们配置免密码登录的用户不是root用户(比如是mhatest用户),那么需要注意以下几点:

    1. 将Manager的配置文件中指定的 manager_workdir 目录的权限修改为免密码登录认证的用户权限。比如,我们在配置文件中写到: manager_workdir = /usr/local/mha , 那么一定要确保

    chown -R mhatest:mhatest  /usr/local/mha 

    2. 将Manager的配置文件中指定的remote_workdir 目录也在对应的node节点将权限改为免密码登录认证的用户权限,比如,我们在配置文件中写道: remote_workdir = /home/data/mha, 那么一定要确保

    chown -R meatiest:mhatest /home/data/mha

    5. 配置MHA Manager

    5.1 配置MHA的Manager

    5.2 配置检查

    5.3 通过master_check_status脚本查看Manager的状态

    5.4 启动MHA Manager 即可正常运行

    5.5 再次check MHA 的Manager 是否启动成功

    6. MHA 功能分离实现

    6.1 自己监控,调用mha进行切换

    有时候,我们可能因为各种原因不想让MHA承担监控和切换的全部工作。 或许是因为不相信它,或许是因为特殊的业务逻辑,那么如果我们想自己来监控数据库的可用性,而在我们自己确定数据库故障时,用MHA作为主从切换的 工具呢 ?

    其实也很简单,在上面安装完MHA 的 Manager节点完后,会有一个masterha_master_switch 脚本,他就是MHA本身的切换脚本,所以完全可以调用他来实现手动的数据库切换。

    我们直接打开这个脚本就可以看到:

    ······省略部分·······

    # For master failover                 // 当master宕机时,可以用下面类似的形式调用

    masterha_master_switch –master_state=dead –global_conf=/etc/masterha_default.cnf –conf=/usr/local/masterha/conf/app1.cnf –dead_master_host=host1

    # For online master switch        //当master在线切换时,可以用下面类似的参数

    masterha_master_switch –master_state=alive –global_conf=/etc/masterha_default.cnf –conf=/usr/local/masterha/conf/app1.cnf

    See online reference (http://code.google.com/p/mysql-master-ha/wiki/masterha_master_switch) for details.

    =head1 DESCRIPTION

    See online reference (http://code.google.com/p/mysql-master-ha/wiki/masterha_master_switch) for details.

    6.2 自己设置主从切换时的逻辑

    如果我在故障发生时,由于业务架构的原因,不想让MHA按照既定的原则切换Master,而是按照我们自己的设定进行故障处理该怎么做呢 ?

    在上面安装完MHA 的 Manager节点完后,会有一个 master_ip_failover , 我们根据自己的需求将此脚本更新为我们想要的操作即可。 这里举个例子,如果我们的数据库复制群是建立在Atlas为proxy的基础之上的话,我们想要做到在主库宕机后,在proxy里自动下掉,或者在主库发生故障时将主库的Keepalive停掉,使得虚拟IP被切换到备库上去,我们就可以在此脚本中加上一些操作满足我们的需求。

    至此,MHA的简单原理和部署已经告一段落,后续我会专门再总结一下MHA高可用性能的测试:

    http://www.foreverlakers.com/2017/05/mysql-mha原理(二)/

    参考

    HA方案之MySQL半复制+MHA+Keepalived+Atlas+LVS

    https://yq.aliyun.com/articles/58920

  • MySQL 高可用(上)

    背景

    MySQL的高可用方案在生产环境中应用非常普遍,顾名思义,它的存在意义就是为了保证数据库可以实现高可用,不阶段的为我们服务。 那么当前都有哪些比较常用的高可用技术呢?

    MySQL的各种高可用方案,大多是基于以下几种基础来部署的:

    1. 基于主从复制;
    2. 基于Galera协议;
    3. 基于NDB引擎;
    4. 基于中间件/proxy;
    5. 基于共享存储;
    6. 基于主机高可用;

    那么,这么多方案,到底哪个才是适合自己的使用场景呢?   或者说我们衡量一套高可用方案的标准是什么呢?

    1. 故障切换响应时间(这个是很重要的一个因素)
    2. 服务资源的利用率(有些高可用的框架导致备份从库占用过多)
    3. 切换后对线上服务的影响(比如切换后是否会造成数据紊乱,或无法提供线上服务)
    4. 维护成本和难度(出问题了还是得运维亲自上啊)
    5. 是否具有灵活的二次开发特性(可以改造适用于自己的生产环境)
    6. 是否会产生脑裂等常见的问题

    我们后面赘述的方案都将经历上述标准的考验!

    基于主从复制的高可用方案

    1. 双节点主从复制的高可用方案

    双节点是小型规模数据库的最常态。 搞两台服务器,分别搭建两个MySQL,做个一主一从或者双主模式,在master节点发生故障后,利用keepalived/heartbeat的高可用机制实现快速切换到slave节点。

    %e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2016-12-24-%e4%b8%8a%e5%8d%8811-27-01

    两台机器分别安装了keepalived,用一个虚IP(VIP)实现mysql服务器的主备自动切换功能。当master宕掉后,keepalived会自动接管这个VIP,使用slave继续提供服务。在这样的集群中,Master对外提供全部的服务,Slave处于备份状态。这是最简单的高可用架构!那么他的质量如何呢? 我们用上面的标准来衡量他一下:

    高可用特性 特性(个人意见,仅供参考)
    故障响应时间 很快,秒级(当然这个也和keepalived配置的故障切换方式有关系)
    服务资源的利用率 较低,从库基本上没有投入使用,只是处于备份状态。
    切换后对线上服务的影响 较大(这个得根据keepalived配置的故障切换方式,也和主从延迟等状态有关系。单纯的切换IP很快,但是如果想要做到主库宕掉以后的差错补齐的话恐怕还需要一定的时间)
    维护成本和难度 较简单(但是直接切换IP后,如果故障切换的不是很完美,那么后续的数据修复就比较麻烦)
    是否具有灵活的二次开发特性 说白了keepalived只是一个虚IP的切换机制,至于什么时候切换,怎样切换得自己来掌控,个人觉得其实这样也好。 可以根据自己的业务场景来配置。
    是否会产生脑裂等常见的问题 可能会

    接下来我们试着搭建这样一套最简单的MySQL高可用架构。

    1. 搭建一个拥有正常复制状态的主从结构,具体过程可参考之前的博文(Linux搭建mysql5.7 GTID 主从复制环境

    2. 安装配置keepalived,具体可参考之前的博文(http://www.foreverlakers.com/tag/keepalived/),我这里将我的keepalived配置文件贴出来供参考

    Master :

    Slave :

    test_shutdown.sh :

    3. 分别在Master 和 Slave上启动keepalived 进程,就会看到在Master的eth0网卡上多了一个VIP,10.75.250.1.

    4.  然后我们测试将Master上面的MySQL进程shutdown,发现VIP立刻被切换在Slave上面,Successed!

    上面的过程看似非常简单,但其实存在很多缺陷和漏洞,例如:

    1. 如果Master 宕机时主从有延迟,那么就会造成数据的永久丢失。
    2. 当Master所在的服务器恢复正常后,我们的系统不能自动的去发现它并恢复。
    3. 如果从库的配置劣与主库,那么有可能在故障切换之后从库也发生问题。

    那么我们应该怎么解决这些问题呢 ?

    1. MySQL 开启双1 参数(酌情而定)保证服务器宕机时,Master本身不会丢失数据。
    2. 使用MySQL的半同步复制来避免主从延迟,或者用MySQL的高版本并发复制尽量减少主从延时,或利用NFS等工具实时备份binlog。
    3. 开启GTID复制模式,并且打开Slave的log-slave_updates参数。
    4. 把两个主从节点的auto_increment_increment(自增步长)和auto_increment_offset(自增起始值)设成不同值。其目的是为了避免master节点意外宕机时,可能会有部分binlog未能及时复制到slave上被应用,从而会导致slave新写入数据的自增值和原先master上冲突了,因此一开始就使其错开;当然了,如果有合适的容错机制能解决主从自增ID冲突的话,也可以不这么做;
    5. 加强从库的硬件配置。
    6. keepalived的检测机制需要适当完善,不能仅仅只是检查mysqld进程是否存活,或者MySQL服务端口是否可通,还应该进一步做数据写入或者运算的探测,判断响应时间,如果超过设定的阈值,就可以启动切换机制。
    7. keepalived最终确定进行切换时,还需要判断slave的延迟程度。需要事先定好规则,以便决定在延迟情况下,采取直接切换或等待何种策略。直接切换可能因为复制延迟有些数据无法查询到而重复写入。

    其实,到这里我们可能会想,能不能将MHA或者MMM这类型的成熟且开源的高可用解决方案应用在这种只有一主一从的场景中呢?这样的话,就会方便很多?其实也是可以的,不过这个扯起来就有些远了,我们后面在讲MHA的时候再具体谈谈吧。

    这里稍微再扯一点关于宕机后的主库恢复。 比如宕机的主库服务器 A 经过运维处理恢复正常了,这时候新的主库B 已经在正常工作了,我们应该怎么将它重新纳入我们的集群中呢?  再想直接做主库是不现实了,那么做从库需不需要重新拉备份呢 ?

    遇到这种情况,第一步应该做的是在B执行show slave status 拿到当时事故发生时B的复制状态,在A上执行show master status得到A的binlog记录信息,对比两者来确认当时事故发生时,是否有主从延迟导致的数据丢失。 如果发现在B上得到的Relay_Master_Log_File和Exec_Master_Log_Pos与A 执行show master status的结果一致,那么可能事故并没有造成数据丢失。但是如果前者大于后者,那么就要确认是否有数据丢失,并针对性的进行恢复。

    然后A是否需要重做也是分情况的。如果你没有开启GTID,那么或许可以尝试着去拿到B上show slave status 的结果,记录当时事故发生点对应的relay-log,并从relay-log中解析出B当时具体发生的事务。  然后去对比B的binlog看这些事务刚好发生在B本身的哪个file和pos 。如果确认了,或许可以尝试着直接从A上change master到B上。 否则就只能重做了。

    如果开启了GTID,那么事情就会简单许多。 可以很容易就找到那个position,并跟上复制。

    2. 多节点主从复制高可用方案

    如果我们把上面的双节点简单扩展一下,变成如下的架构:

    %e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2016-12-24-%e4%b8%8b%e5%8d%886-01-11

    其他的都一样,只是在Master后面又多加了几个新的Slave。 当Master出问题的时候,Keepalived依旧将VIP飘到了Slave 1上,但最大的问题就在于其他的Slave也需要将自己的复制源从Master改为Slave1 。 复制源修改的命令语法很简单即CHANGE MASTER TO MASTER_HOST='xxx', MASTER_LOG_FILE='xxx', MASTER_LOG_POS=nnnn。而难点在于,由于同一个事务在每台机器上所在的binlog名字和位置都不一样,那么怎么找到Master当前同步停止点,对应Server 1master_log_filemaster_log_pos是什么的时候就成为了难题。这也就是为什么M-S复制集群需要使用MMM,MHA这样的额外管理工具的一个重要原因。 这个问题在5.6的GTID出现后,就显得非常的简单。由于同一事务的GTID在所有节点上的值一致,那么根据Slave2当前停止点的GTID就能唯一定位到SLave1上的GTID。甚至由于MASTER_AUTO_POSITION功能的出现,我们都不需要知道GTID的具体值,直接使用CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION命令就可以直接完成failover的工作。

    但这里还有一个问题,假如Slave 2 或者 Slave 3在Master出事故的时候它的复制进度比Slave 1还快呢?  也就是说Slave 2 的数据还领先于Slave 1 ,这时候即使使用了GTID 也无济于事了,因为Slave 2 即将应该执行的Position在Slave 1中根本就没有执行过呢,它又怎么能给你呢?   所以,在进行change master之前,还得有一步差异化数据的抵消,即将所有slave中选出那个在Master出问题后复制进度最快的,将它的binlog日志作用到其他Slave上,使其他Slave的复制进度和他保持一致。 然后就可以随便推荐一台作为新的主库了。  MHA 就是这样做的。

    所以,一般这种复制形式就可以应用MHA等开源解决方案去保证数据库的高可用。

    基于Galera协议的高可用方案

    最近,Galera又火了一把,不过可惜的是不是因为他自己。2016年12.12日,MySQL官方发布了Group Replication(GR),提供了MySQL集群化解决方案。 在此之前,应用最多最广最受欢迎的应该就是Gelera了。于是人们开始拿两者做各种对比了。甚至网上有很多人说Gelara将死。 不过作为支撑N载集群化解决方案的Gelera本身的价值是不可估量的。国内很多大公司至今都依赖于它实现MySQL的集群化。

    Galera是Codership提供的多主数据同步复制机制,可以实现多个节点间的数据同步复制以及读写,并且可保障数据库的服务高可用及数据一致性。
    基于Galera的高可用方案主要有MariaDB Galera Cluster和Percona XtraDB Cluster(简称PXC),目前PXC用的会比较多一些。

    Gelera的实现架构示意图见下(图片摘自网络):

    yy1

    如上,在底层采用wsrep接口实现数据在多节点间的同步复制。

    yy

    如上,客户端请求update更新数据,galera集群中一台服务器收到请求后,本地进程反馈OK,client则提交需要commit更改的数据,server收到提交事务后,所有对数据的更改都会被write-set收集起来,并将write-set的记录内容发送给其他节点。write-set会在每个节点执行之前都会进行认证certification,若认证通过,则节点应用write-set记录更改数据;若认证失败,该节点将discard丢弃write-set,其他节点则回滚rollback该事务。

    作为Gelera 中的佼佼者,PXC是最受欢迎的,他都有哪些特性呢?

    PXC的优点

    • 服务高可用;
    • 数据同步复制(并发复制),几乎无延迟;
    • 多个可同时读写节点,可实现写扩展,不过最好事先进行分库分表,让各个节点分别写不同的表或者库,避免让galera解决数据冲突;
    • 新节点可以自动部署,部署操作简单;
    • 数据严格一致性,尤其适合电商类应用;
    • 完全兼容MySQL;

    虽然有这么多好处,但也有些局限性:

    • 只支持InnoDB引擎;
    • 所有表都要有主键;
    • 不支持LOCK TABLE等显式锁操作;
    • 锁冲突、死锁问题相对更多;
    • 不支持XA;
    • 集群吞吐量/性能取决于短板;
    • 新加入节点采用SST时代价高;
    • 存在写扩大问题;
    • 如果并发事务量很大的话,建议采用InfiniBand网络,降低网络延迟;

    事实上,采用PXC的主要目的是解决数据的一致性问题,高可用是顺带实现的。因为PXC存在写扩大以及短板效应,并发效率会有较大损失,类似semi sync replication机制。

    说实话,Gelera我也没有用过,仅仅停留在理论层而已,并没有时间经验。所以也没有什么深入的讲解,日后若有幸用到,可以试试。

     

    参考:

    MySQL高可用方案选型参考