mysql 高可用方案

191 篇文章 87 订阅 ¥9.90 ¥99.00


引言:


AliCloudDB HA 系统是为阿里云 mysql,sqlserver,pgsql 三大数据库提供实例高可用的一整套技术方案,确保系统能够在故障中快速恢复。同时 HA 也满足日常运维管理中涉及到主备切换的需求。由于 mysql 在业内使用最为广泛,所以本系列先介绍 mysql 实例高可用的相关技术。



基本架构:


目前使用最为广泛的实例架构是采用一主一备 share-nothing 的结构。数据链路支持 RLB + dbnode 与 RLB + proxy + dbnode 两种。为简便起见,本文以 proxy 链路,引擎为 innodb 的实例为例介绍。
    


主备同步模式支持半同步,与异步两种方式,强同步在 mysql5.7 中将被支持。


这里简要介绍下三种同步方式的区别:

  • 异步模式:主库收到 commit 请求后,依次执行:写 redo log prepare,写入 binlog,写 redo log commit,返回客户端成功。

  • 半同步模式:主库收到 commit 后,依次执行 redo log prepare,写 binlog / 发往备库 (两个步骤并行),等待备库回复收到 ack,redo log commit,给用户回复成功。

  • 强同步模式:主库收到 commit 后,依次执行 redo log prepare,写 binlog / 发往备库(并行),等待备库 fsync 到磁盘后,redo log commit ,给用户恢复成功。

以上步骤中,写入 redo log 步骤受参数 innodb_flush_log_at_trx_commit 影响。 分为 0,1,2 三种设置,具体含义这里不再赘述。写入 binlog 步骤受 sync_binlog 参数影响,具体数字含义,也不再赘述。在两个参数双 1 条件下,数据最为安全可靠,性能略有下降。本文假设我们都是设置在双 1 条件下。



健康检测与切换类型:

健康检测:


HA 使用 update 语句对 mysql 实例分别通过 VIP,物理 IP 进行检测,这样检测的优点是可以检测从 VIP 到用户实例主库的整条链路的可用性,同时配合备库的 io 线程的健康状况,避免 HA 到用户主库网络故障情况下,主库实例健康时的误判。


HA 每次 update 成功时,HA 都将主库的时间戳记录到 HA 当中,同时更新主备库的心跳表,让备库同步主库写入的时间戳,当发生切换时,对比 HA 中与实例备库中保存的时间戳,可以得到备库大致的延迟。作为主备延迟的判断依据之一。

当实例发生连接超时,连接重置,更新超时,socket 超时时都被称作故障切换。



普通切换

当发生 mysql 实例版本升级,规格升级,刷新实例参数等情况时,需要对实例做主备切换。切换基本步骤如下:

  • 预检查主备延迟,如果延迟较大,那么直接退出切换,等待下次切换。

  • 如果延迟在一定范围内,那么进入切换流程,调用 proxy api 切换 VIP 指向备库。Proxy 此时会 hold 住用户新的连接和请求,不会访问备库(桥接)。关于桥接的具体详情可以参考 proxy 技术方案的文章。

  • kill 主库连接,设置 read_only 参数为 ON。等待主库瞬间连接上来的事务结束。

  • 读取主库 master binlog 的位点信息,等待备库同步到该位点,由于之前进行过预等待所以此步骤不会等待很长时间,根据实际运行中数据观察可以控制在数秒以内。

  • 备库打开 read_only 为 OFF

  • 调用 proxy api 放开用户连接的请求。整个切换过程不会超过 10S,用户会感觉到服务器卡住一小段时间后,恢复正常。

 

故障切换

mysql 实例发生故障的环节可能多种多样,这里仅以主备库采用异步复制模式,并且主库所在主机故障导致的切换为例来讲解基本的故障恢复流程,其他类型的故障后面会再综合介绍。

  • 当主库自身发生故障时,HA 连接主机后,返回的错误类型是连接超时,或者收到主库返回的 rst 包,那么进入切换流程。

  • 检查备库延迟自身 SQL 线程延迟,如果有延迟,那么不切换,等待备库应用 relaylog。

  • 当备库 SQL 线程没延迟后,尝试连接主库,获取主库 master binlog,如果能够获取,那么就等待备库跟上主库到该位点。如果不能获取(一般都是如此),那么对比主备库时间戳,如果时间戳在一定范围内(主备可能存在数据不一致),那么根据用户指定的策略决定是否切换。


A, 如果用户指定可用性优先,那么 HA 会将用户连接切换至备库,数据可能丢失,已经通报给用户。

B, 如果用户指定可靠性优先,那么不会切换 VIP,人工介入重启主库或主实例,或拷贝 redo log,修复数据,确保主备一致后,提供服务。


由于异步模式在有主备 IO 线程延迟情况下可能存在数据丢失,我们数据库内核组专门开发了 double binlog 复制方式,用于专门判断在切换时是否存在数据丢失,如果存在,那么可靠性优先条件下不切换,可用性优先条件下可以切换。


在用户指定了半同步模式下,也有可能导致主备数据不一致,但是不会引起数据丢失(数据丢失的定义是用户 commit 后收到成功的回复,但是数据库内没有该数据。对于执行超时,或者执行异常,客户端认为是 unknown 状态,那么数据库可以选择丢弃该事务,或者应用该事务)。Semi-sync 条件下,主备故障切换后,备库按照新主库备份集来重新搭建,确保主备数据一致。

其他故障切换:
    


以上图中各处都有可能发生故障,那么对于不同的故障情况,都要分别逐一考虑,目前 HA 从整体上已经保证了以上各种故障条件下,可以在用户指定策略下按预期切换。考虑篇幅过长,每种情况的分析放在下次分享中,这里暂不作介绍。



 

HA 自身高可用与高可靠


HA 通过多台机器采用多 MASTER 结构平衡负载,每台 HA 负责该 region 的一部分实例,并动态平衡,同时如果有一台 HA 发生故障,那么其他 HA 机器会争抢该 dead HA 所负责实例,然后再次平衡负载,实现方法既可以很简单,也可以很复杂, ha 这里由于考虑多单元部署的成本问题,使用 metaDB 中一个表作为负载均衡器,使用另外一张表作为 HA 心跳表,同时 metaDB 使用一主多备方案,避免单点故障。整体上解决了 HA 自身的高可用问题。



总结:


本片主要简单讨论了 HA for mysql 异步复制条件下基本切换流程, 没有介绍各种切换方式的优缺点及各种讨论,以及半同步条件,for mssql, for pgsql 条件下的切换,业内其他厂商如何解决数据库可靠性与可用性问题的相关内容。敬请期待。






mysql 高可用方案漫谈(二)


引言:


上一期介绍了对于单个实例主备切换的涉及的业务细节,这次我们更深一步,讨论下真实场景中主库故障,或者网络出现故障时涉及到的问题。如果有不妥的地方,欢迎大家指正。




主库故障:

故障分类


一般的,我们会发现 mysql 不可用的原因有几下几类:

  1. 主机硬件损坏,导致主机 hang 死,或者操作系统 crash。此时客户端连接主机上的 mysql 进程时的表现是连接超时。因为不会回复 ack 包。此种情况与网络中断不能回包的表现是一样的,所以对于外部是无法判定是主机 down 还是网络故障的。我们遇到过 raid 卡损坏,磁盘故障,电源模块损坏,起火等等。

  2. 操作系统配置或者环境问题,比如 ipfilter 某个参数配置过小或者 BUG,设置出错等,导致 drop 掉某些包,会导致实例部分连接没有响应,但是主机可能还可以登录。此时与 1 的外部表现也是相同的。

  3. mysql 自身 BUG,或者某些异常 sql 导致 mysql 自身 crash,此种情况是 mysql 进程 crash,主机是完好的,所以可以通过连接主机其他端口验证出是进程故障还是主机故障。

  4. mysql 实例性能问题,比如用户执行一个大事务,刷 pageCache 或者写 log,导致磁盘 IOUTIL 打满,此时表现是连接超时,或者连接可以建立,但是执行 update 语句超时。此时主库 log 一般是可以正常传送到被库的。


针对以上故障,我们可能需要进行故障切换,故障切换最重要的两条原则,1)保证数据安全,保证数据可靠性。2)在一定时间内能快速响应,提高可用性。




可靠性保障:

可靠性概述


可靠性保障最重要的就是要确保被库与主库数据保持一致,进一步就是说主库写入的 binlog 都要能够传递到备库。在异步模式下,是无法保证的,在半同步模式下,大部分情况可以保证,为什么说是大部分情况,因为有可能是备库刚刚 down 机,启动后,正在 IO 线程追主库 log,此时复制还是异步模式,但追上后,才会自动转为半同步模式。如果此时主库再 down 机,那么也一定会有部分 log 还在主库上。如果说要保证一定传到备库,保证数据强一致,那么当备库 down 机时,主库就不应该继续提供服务,此种用法在其他主流数据库中也可以设置,但是很少使用,因为对可用性影响较大,因为如果一旦备库 down 机,或者主备间网络断开,那么主库可用性立即就受到影响,这种对于一般用户来说是不可接受的。进一步,有人引入了一主多备模式,当有一个备库返回已经收到最后一条日志后,就可以给用户返回 commit 成功,这样提高了主库的可用性,同时也提高了成本。


言归正传,在一主一备的阿里云主流模式下,我们对于需要较高可靠性的用户,推荐使用半同步模式。集团内部的 MHA 系统提供了当主库故障时,从原主库同步 log 到备库,追上一段后,再提供服务的方案,此种方案能 work 的前提是原主库依然可以连接并且读取磁盘,并且会牺牲一段可用性时间,好处是可以补充一段 binlog,让备库数据与主库一致。其实是可以作为一个比较好的补充手段。


RDS 这里对用户实例做了 24 小时不间断的被库延迟监控,所以对于数据延迟的实例会提前报警,避免当主机完全不可恢复时,数据丢失。


## 如何应对


考虑这样的场景,主备库分别部署在 A,B 两个机房做容灾,HA 的两个节点也分别部署在两个机房,当 A,B 机房间发生网络故障,但是 A,B 机房自身正常时,两边的 HA 都分别看见对端的实例节点放生故障,会将自己机房的实例提升为主库,那么此时如果两个机房都有流量进来,那么就可能导致数据库 “双写”,也就是会发生著名的 “脑裂” 问题。


如果要解决 “脑裂” 问题,两个节点是不够的。那么我们引入了第三个节点,部署在另外一个机房,该节点无数据,只负责 “脑裂” 判定。这样构成了一个三个节点的三角模式(mongoDB,mssql 都是类似做法),三个点可以分别部署 zookeeper 客户端并且选主,同一时刻,3 个节点间只能有一个为 leader。



3 个节点中任意两个节点活着,那么实例可用。如果 3 个节点中两个或者 3 个节点挂掉,实例不可用。当 A 机房挂掉,或者实例在 A 机房的主机挂掉,那么 leader 在 B,C 机房产生,此时由于 B 机房可以连通 leader 那么认为自己可以继续服务;C 机房挂掉,那么 leader 在 A,B 中产生,A,B 都能连通 leader ,那么仍然都可以继续服务。




网络故障场景


考虑网络故障情况,


A 为主,B 为备,C 为裁判:

  1. 当 A 机房与 B 机房网络不通,3 个节点都正常,A 到 C,B 到 C 都正常。

    leader 在 A,那么 A,C 为多数派,A 继续提供服务。

    leader 在 B,那么 A 摘除自己,B,C 之间重新选择 leader ,将 B 提升为新主库。

    leader 在 C,那么 A, B 服务不受影响,但是备库复制线程中断。

  2. 当 A 机房与 C 机房网络不通,

    leader 在 A,那么 C 不能获取状态,摘除,B 能与 A leader 连接,继续 work,A 由于与 B 连通,投票多数,那么继续 work ,不受影响。

    leader 在 B,那么 A,C 节点都与 leader B 可以通信,那么整体都可以 work, 无任何影响。

    leader 在 C,那么 A 与 C 不通,那么 A 自己 down 掉自己,B 与 leader C 通,所以 B 可以 work , 将 B 中实例节点提升为主库。

  3. 当 A 与 B,C 机房都不通,

    leader 在 A,B,C 重新选 leader ,那么 A 自己不 work,然后 B 提升为主库。

    leader 在 B 或者 C, 不必选 leader , A 自己不 work,然后 B 提升为主库。

  4. 当 B 与 C 不通,与 A 通,B 为备库,自己摘除自己,不影响可用。

    leader 在 A,B 与 leader A 通,那么不受影响。

    leader 在 B,A 和 B 构成多数派,继续提供服务。

    leader 在 C,那么由于 A 与 C 通,B 摘除自己,主库 A 继续提供服务。

  5. 当 B 与 A,C 都不通,A,C 之间通,那么在 A,C 间重新选 leader , 然后 A 继续提供服务。

  6. 当 C 与 A,B 都不通,那么 A,B 将重新选择 leader ,A 继续提供服务。


当 B 为主库时,分析与上面类似,综上,可以认为当主库本身节点与 leader 节点不通,或者自己是 leader 节点,但是与另外两个节点都不通,自己成为少数派时,会发生 failover,其余情况都可以正常工作。解决了 “脑裂 “问题,关键点就在于当节点自身发现是少数派时,自我管理,自己将自己杀掉。


同时,HA 按照正常逻辑提升备库为新主库,保证可用性。


#结合现实


回到现实中,因为条件有限,有些时候没办法都部署三机房,所以在两机房时,如果是 C 节点与 B 部署在一边,A 节点此时是主库,那么当 C 所在的机房整体 down 机,那么数据库主节点 A 由于与 leader 节点不通,将自己关闭自己的写入,并且此时由于 B 与 C 所在节点 down 机,B 也无法提供服务,那么此时实例就无法提供服务。


如果 A 节点主库与 B.C 所在的机房网络不通,但是 B,C 机房可以提供服务,那么主库会自动 failover 到 B 节点,此时 B 和 C 选出一个 leader , 继续提供服务,没有问题。




总结


本期主要从实际角度出发,阐述了一些场景,下一期会从 2pc,3pc, 分区一致性等理论角度来探讨下如何保证节点间的数据一致性。以及 mysql 主库故障并且 log 未传递到备库时,恢复备库可能的手段。






mysql 主备复制下的可靠性漫谈(三)


引言:


前面两期主要针对各种故障条件下,对数据可靠性带来的挑战及普通应对策略。本文主要针对在主备非强同步复制模式下,能否保证数据可靠性来讨论。




复制模式概述:


异步模式:主库收到 commit 请求后,依次执行:写 redo log prepare,写入 binlog,写 redo log commit,返回客户端成功。


半同步模式:主库收到 commit 后,依次执行 redo log prepare,写 binlog / 发往备库 (两个步骤并行),等待备库回复收到 ack,redo log commit,给用户回复成功。这个有一个等待 ack 的超时,当超过设置的时长,那么自动降级为异步模式;当网络或备库恢复后,备库 IO 线程开始追赶主库,当追上后,复制模式会自动升级为半同步模式。


强同步模式:主库收到 commit 后,依次执行 redo log prepare,写 binlog / 发往备库(并行),等待备库 fsync 到磁盘后,redo log commit ,给用户恢复成功。



保证可靠性:

异步模式下,由于主库写入事务时,不会传递到备库(无论物理复制还是逻辑复制),那么当主库 down 机时,备库数据和主库是很可能不一致的,所以此时是无法保证可靠性的。对于我们阿里云用户使用的 mysql 库,在此模式下就没任何办法了么?其实不是,在此模式下,我们提供了以下的措施来最大限度的保证主备一致性:

  1. 备库一定是在应用完所有传递到备库的日志后,才开放可写。这样就最大限度保证备库的数据线是一致的,不会导致双写的问题(一边应用日志,一边接受写入)。

  2. 主库增加时间戳,通过复制关系同步到备库,当主库故障时,HA 系统(数据库高可用系统)通过比对最后一次成功写入主库的时间戳及备库上从主库接受到日志后应用掉后的时间戳进行比较,当大于某个阀值时,不做链路切换动作。这样能够保证主备间数据不一致的时间长度在可控范围内。

  3. 判断主库故障的条件更加苛刻,当不是主库所在主机是不可恢复的故障时,优先使用主库重启的方式来解决,确保数据线的一致性。


半同步模式下,当网络与主备库都正常情况下,主备库的数据一定是最终一致的(备库需要应用 relay 日志),当主库故障时,要么事务在主库还没有应用,没有传递日志到备库;要么事务在主库应用了,日志也传递到了备库。所以最终是一致的。



那么是不是半同步下,数据就不丢了呢?我们前面说过,当网络,和备库出现间歇性问题时,那么半同步会降级为异步,那么如果恰恰在此时,备库的 IO 线程正在追赶主库的 binlog 位点,但是还没有完全同步上,主库 down 了 (也就是说此时出现延迟的情况下),主备数据就会出现不一致。



针对这个问题,我们研发了 double binlog 复制模式,该模式是在半同步基础上更进一步,在主备库间除了半同步复制通路,同时还有一个异步复制通路,平时在主备库及网络都健康情况下,由半同步通路持续的保持复制关系,确保主备数据一致;但是当在备库或主备间网络出现问题,一旦备库或网络恢复后,备库不再使用单一的链路来复制 binlog,会同时开启两条复制链路,一条继续从上次备库最后一次接到的位点来复制,一条从主库写入的最新一条事务日志来复制,那么落后的复制不必追赶到最新的主库 binlog 位置才升级为半同步,而是追赶到备库恢复后的位点即可。这时两条复制通路的 binlog 就可以完整接上,然后等待备库继续掉日志后,主备数据就完全同步了。




总结:


所以通过这个特性,我们能做到在主备出现延迟后,依然能够保证主备的一致性。目前金融专有云已经开始使用该复制模式,对数据要求性高的朋友依然可以使用 mysql 一主一备的低成本方式来满足企业的日常需求。




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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值