比如像MHA,它自己也必须搭建成Master-Slave架构,有种跌入了递归深渊的感觉。为了更好地解决外部HA模块的高可用,一致性协议进入了视野,ZooKeeper方案应运而生,用一套ZooKeeper来管理HA,系统也变得越来越复杂。
实际上半同步复制技术也存在主备不一致的风险,原因在于当master将事务写入binlog,尚未传送给slave时master故障,应用切换到slave,虽然现在slave的事务与master故障前是一致的,但当主机恢复后,因最后的事务已经写入到binlog,所以在master上会恢复成已提交状态,从而导致主从之间的数据不一致。因此要做到强一致性,HA模块还要分析新老主库的binlog和relaylog,实现一系列复杂的回滚回补逻辑。
与其在外部HA这条路越走越远,不如把Paxos/Raft等一致性协议直接集成到MySQL内核中。Galera Cluster、MySQL Group Replication(MGR)等方案在社区中开始涌现出来。2016年,阿里巴巴数据库团队开始在集团内部沉淀一致性协议的实践经验。我们自研了一致性协议库X-Paxos并集成到AliSQL 5.7中,称之为X-Cluster。2017年第一年支持了双十一大促,此后开始大范围推广。经过2年的内部打磨,该版本改名三节点企业版在2019年7月正式上线公有云售卖。本文暂不比较三节点企业版和社区MGR等方案的优劣,下一章节会通过介绍我们的高可用体系,来说明即使数据库深度集成了一致性协议,依然存在很多挑战。
基于Paxos/Raft等一致性协议的选主,都会采用租约(lease)的方案。选主最大的问题是要避免“双主”出现。如果当前Leader被网络隔离,其他节点在租约到期之后,会自动重新发起选主。而那个被隔离的Leader,发送心跳时会发现多数派节点不再响应,从而续租失败,解除Leader的状态,这也避免了“双Leader”现象出现。Follower约定在lease期间不发起新的选主,Leader先于Follower lease超时,从时序上最大程度上规避了“双主”问题的出现。不过实际上,从一致性协议角度来说,老主降级流程即使由于各种原因略微延后,也不会造成正确性的问题。比如Raft协议中,新主选出后,老主的term发起的提案是无法达成多数派的。避免“双主”本质上是为了尽快的通知外部Client主库已经变化,从而及时进行链路切换。
权重选主
权重选主理解上很简单,就是给每一个节点一个权重值,在主库不可用时,优先选取权重高的节点当新的主库。从实现上来说,权重是对Leader lease的一个微小修正,对于低权重的节点,每次会在lease原有timeout数值的基础上随机增加一个小的△t,权重越低,△t越大。基于这样的timeout策略,就可以保证在lease超时后,高权重的节点大概率会优先发起选主投票。权重选主主要应用在在三地五副本的场景下,在中心机房主库不可用时,我们希望优先切换到同城的另一个节点,来避免不必要的App跨城调用延迟。这样的设计既能保证高可用,也能保证高质量的服务。(三地五副本部署架构参考:《RDS三节点企业版 一致性协议》中跨域五副本一节)
这里要补充说明的是,分布式环境下的通信有很多不确定性,因此权重选主只是一个弱限制。在某些情况下依然可能选出一个低权重的节点当Leader,这并不影响整体系统的可用性。在实践过程中,我们发现目前的机制已经可以满足大部分的需求。
状态机诊断
从数据一致性角度来说,选主流程结束后,新的Leader必须回放完所有的老日志才能接受新的数据写入。因此,成功选主并不等价于服务可用,实际的不可用时间是选主时间(10s)和日志回放追平时间之和。三节点企业版在状态机应用日志的逻辑中,复用了MySQL的Slave和Worker线程,支持基于Table、Commit Order和Write Set三种模式的并行回放。在遇到大事务、DDL等场景下,和传统的Master-Slave复制模式一样,Follower可能会产生比较大的回放延迟。假如此时恰好主库出现故障,新选主的节点由于回放延迟,服务不可用时间充满了不确定性,那又如何保证SLA呢?
故障有可恢复和不可恢复之分,通过我们观察,除了那种机器宕机、磁盘坏块这类彻底恢复不了的场景,大部分故障都是短期的。比如网络抖动,一般情况下网络架构也是冗余设计的,可能过一小段时间链路就重新正常了。比如主库OOM、Crash等场景,mysqld_safe会迅速的重新拉起实例。恢复后的老主一定是没有延迟的,对于重启的场景来说,会有一个Crash Recovery的时间。这个时候,最小不可用时间变成了一个数学问题,到底是新主追回放延迟的速度快,还是老主恢复正常的速度快。因此,三节点企业版中,我们做了一个状态机诊断和主动切换的功能。
在三节点企业版的内核中,通过状态机诊断接口,服务层有能力向协议层汇报当前状态机的健康状况,包括回放延迟、Crash Recovery、系统负载等状态。当状态机健康状况影响服务可用性时,会尝试找一个更合适的节点主动切换出去。主动切换功能和权重选主也是深度整合的,在挑选节点的时候,也会考虑权重的信息。最终,服务恢复可用后诊断逻辑会自动停止,避免在稳定Leader的情况下产生不必要的切换。
磁盘探活
对于数据库这样有状态的服务来说,存储是影响可用性的重要因素之一。在本地盘部署模式下,数据库系统会遇到Disk Failure或者Data Corruption这样的问题。我们曾经遇到过这样的情况,磁盘故障导致IO卡住,Client完全无法写入新的数据。由于网络是连通状态,节点之前的选举租约可以正常维持,三节点自动容灾失效导致故障。有时候还会发生一些难以捉摸的事情,由于IO已经完全不正常了,进程在kernel态处于waiting on I/O的状态,无法正常kill,只有重启宿主机才能让节点间通信完全断掉触发选主。此外对于云服务的RDS来说,即使使用云盘等分布式存储,也有底层服务不可用的风险。
针对这类问题,我们实现了磁盘探活功能。对于本地盘,系统自动创建了一个iostate临时文件,定期向其中执行随机数据读写操作。对于云盘这类分布式存储,我们对接了底层的IO采样数据,定期来感知IO hang或者Slow IO的问题。探测失败次数达到某个阈值后,系统会第一时间断开协议层的网络监听端口,之后尝试重启实例。
反向心跳
基于已有的策略,我们已经可以覆盖99%的常规可用性问题。在长时间的线上实践中,我们发现有些问题从节点内部视角发现不了,比如主库连接数被占满,open files limit配置不合理导致“Too many open files”报错,以及代码bug导致的各种问题……对于这些场景,从选举租约、状态机、磁盘探活的角度,都无法正确的检测故障,因此最好有一个能从App视角去建连接、执行SQL、返回结果的全链路检测流程。因此催生了Follower反向心跳的需求,即Follower通过SQL接口去主动探测Leader的可用性。该设计有两个优势:首先是内核自封闭,借助三节点的其他非Leader节点,不依赖外部的HA agent进行选主判定,就不用再考虑HA agent本身的可用性问题;其次和内核逻辑深度整合,不破坏原有的选主逻辑。
整个流程如图所示,假设Node 1是Leader,给其他两个Follower正常发送心跳,但是对外的App视角已经不可服务。当Node 2和Node 3通过反向心跳多次尝试发现Leader的SQL接口不可服务之后,这两个Follower不再承认Leader发来的Heartbeat续租消息。之后若Node 2的选举权重相对较高,他会首先超时,并用新的term发起requestVote由Node 3投票选成主,对外开始提供服务。这个时候Node 2作为新主,也会同时开始给Node 1和Node 3发续租心跳。Node 1在收到新主发来的心跳消息之后,发现term比自己当前term大,就会主动降级成Follower。整个三节点又能回到正常的状态。
https://blogs.vicsdf.com/article/41514
http://www.iocoder.cn/Eureka/instance-registry-renew/
https://zhuanlan.zhihu.com/p/58166044
https://blog.csdn.net/yuu1009/article/details/80778928
https://cloud.tencent.com/developer/article/1683247
https://blog.csdn.net/hzh2007/article/details/7956943?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-15-7956943.nonecase&utm_term=mysql%20%E5%BF%83%E8%B7%B3%E6%A3%80%E6%B5%8B&spm=1000.2123.3001.4430
https://blog.csdn.net/Jerome_s/article/details/53966569?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-11-53966569.nonecase&utm_term=mysql%20%E5%BF%83%E8%B7%B3%E6%A3%80%E6%B5%8B&spm=1000.2123.3001.4430
https://blog.csdn.net/Jerome_s/article/details/53966569?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-11-53966569.nonecase&utm_term=mysql%20%E5%BF%83%E8%B7%B3%E6%A3%80%E6%B5%8B&spm=1000.2123.3001.4430
MHA(Master High Availability)是一种MySQL高可用解决方案,由日本DeNA公司开发,主要用于在故障切换和主从提升时进行快速切换,并最大程度保证数据一致性。
MHA主要由两部分组成:
1、MHA Manager(管理节点),管理节点部署在群集之外,主要用于定期监测群集中的主节点,并在主从切换时负责管理调度切换流程。
2、MHA Node(数据节点),数据节点部署在每个群集节点上,负责在主从切换时对比和应用差异日志。
https://www.cnblogs.com/gaogao67/p/11105996.html
https://www.cnblogs.com/brianzhu/p/10154708.html
https://blog.51cto.com/12980155/2391973
https://blog.csdn.net/weixin_34178244/article/details/92306272
https://zhuanlan.zhihu.com/p/35806767?utm_source=wechat_session
https://blog.51cto.com/net881004/2112536
https://www.cnblogs.com/zhaoyangjian724/p/6199546.html
https://recomm.cnblogs.com/blogpost/6199546
https://www.cnblogs.com/zhaoyangjian724/p/6199546.html
https://segmentfault.com/a/1190000023297973?utm_source=tag-newest
https://blog.csdn.net/pengjunlee/article/details/81583052
https://blog.csdn.net/XDSXHDYY/article/details/97825508