Orchestrator故障检测和恢复:新的开始
Orchestrator是一个开源的MySQL复制拓扑管理和高可用性解决方案。Vitess最近将Orchestrator集成为了其基础设施中的一个本地组件,用以实现集群的可靠故障转移、可用性和拓扑解析。本篇文章首先阐述了Orchestrator故障检测的核心逻辑,并讲述了新的整合如何增加了新的故障检测和恢复场景,使得Orchestrator的操作更具目标导向性。
注意:在本文中,我们在MySQL复制的上下文中采用“primary”替代“master”这一术语。
Orchestrator的全局故障检测
Vitess和Orchestrator都使用了MySQL的异步(async)或半同步复制。为了便于讨论,本文限定在异步复制范围内。在异步设置中,我们有一个primary服务器和多个replica(从服务器)。primary是单一可写服务器,而replica都是只读服务器,主要用于实现读扩展、备份等用途。尽管MySQL支持多可写primary设置,但通常不建议使用,Vitess也不支持(事实上,后者将该设置视为一种故障场景,稍后会有更详细的讲述)。
在异步拓扑中,最关键和重要的故障场景是primary服务器的宕机。可能是服务器崩溃,也可能是网络隔离导致的,其结果就是整个集群无法进行写操作,同时replica也因没有可复制的服务器而被悬置。
常见故障检测方法
如何判断primary服务器健康状况?一种常见做法是检查端口3306
是否打开。更可靠的方法是发送一个简单查询,例如SELECT 1 FROM DUAL
。或者,为了更可靠,我们可以查询一些实际信息,例如状态变量或实际数据。所有这些技术有一个共同的问题:如果primary服务器没有响应怎么办?
一个天真的结论是primary服务不可用,从而启动故障转移流程。然而,这可能是一个假阳性,因为问题可能只是网络故障。丢失一个通信包偶尔会发生,因此数据库客户端通常配置成在错误时重试几次。减少假阳性的方法通常是执行连续多次检测:如果primary健康检查失败,间隔5秒后再次尝试,然后再次尝试,总共进行n次检查。如果第n次检查仍然失败,我们确定服务器确实宕机。
这种检查方式引入了几个问题:
- 何时算是足够检查次数?
- 检查间隔多少才合理?
- 如果primary确实宕机,那么我们浪费了
n*间隔
秒来反复检查,而本可以早点进行故障转移。 - 如果primary实际上是正常的,但它与检测终端的网络之间存在问题,这就产生了一个假阴性,我们错误地进行了故障转移。
考虑第4点:有些监控系统从多个端点运行健康检查,并通过多数端点的协作(一种“仲裁”机制)判断问题是否存在。这种设置必须谨慎使用;为了获得合理的仲裁结果,不同端点的分布位置(跨可用区)至关重要。一旦配置正确,这种三角定位能非常有效。
Orchestrator的检测方法
Orchestrator采用了一种与众不同的三角定位方法。它认识到环境中还有其他参与者:replica。replica通过MySQL协议连接到primary,并请求日志以跟随primary的更新步伐。为了评估primary故障,Orchestrator提出以下问题:
- 我是否无法与primary通信?
- 所有replica是否都无法与primary通信?
如果例外情况是,Orchestrator无法联系primary,但能与replica通信,且replica明确表示它们可以从primary读取,那么Orchestrator判断不存在故障场景。可能一些replica自身不可用,例如网络分区或主机断电导致primary和某些replica均无法访问。但Orchestrator能够从其他可用replica的状态推导结论。
需要注意的是,Orchestrator本身在高可用性配置中运行,其角色跨可用区,并采用仲裁领导机制确保故障转移的可靠性,从而缓解网络隔离问题。但此内容超出了本文范围。
Orchestrator不使用检测间隔和多次测试。它只需一次观察即可采取行动。在幕后,Orchestrator依赖于replica本身以间隔方式运行重试,这正是MySQL复制协议的默认行为,Orchestrator充分利用了这一点。
这种全局视角的方法,使得Orchestrator能够结合自己的检查以及服务器上的检查,从而实现高度可靠的故障检测。例如,如果Orchestrator认为primary宕机,同时所有replica也表示primary宕机,那么故障转移是有充分理由的:复制集群事实上无法接收任何写入,数据变得陈旧,这足以被用户和客户端应用观测到。这种全局方法还允许Orchestrator处理其他场景:例如检测中间级别replica(如复制链中的二级replica)故障的方式完全一样,甚至能进一步细化故障的严重程度。Orchestrator可以区分出primary似乎宕机,而replica还未达成一致的情况,或者replica认为primary宕机,而Orchestrator仍然与其保持通信。
紧急检测操作
如果Orchestrator无法联系primary,但可以与replica通信且它们仍认为primary是可用的,这是否就是事件的终结?
其实不然。primary可能真的宕机,只是replica还没有意识到。若我们足够等待,它们最终会报告故障;但是Orchestrator的意图是通过尽早解决问题来缩短总宕机时间。
Orchestrator提供了一些紧急检测操作,用于加快故障检测。例如:
- 如上所述,Orchestrator无法联系到primary。此时它紧急探测replica,确认它们的状态。通常情况下每个服务器会在几秒内被探测一次,而在紧急操作时探测频率变高。
- 一级replica报告它无法看到primary,其余replica正常,而Orchestrator还能与primary通信。此情景疑点重重,因此Orchestrator对primary执行紧急探测。如果探测失败,问题基本确认,落回到第一个操作。
- Orchestrator无法联系primary,而replica都可以连接primary,但replica上的延迟不断增加。这可能是某种僵局,例如primary被锁定或“连接数过多”问题。此时replica可能是一些较旧的primary连接,新连接无法与primary对接,应用层面可能认为primary不可用,而实际上replica仍保持连接。Orchestrator能分析此情况并紧急重启所有replica的复制连接。这将关闭并重新建立TCP连接。这一操作对于锁定主机或“过多连接”场景十分有效,因为replica通常会在这种情况下失败重连,随后检测到primary故障。
Orchestrator和您的复制集群
一个重要的观察是,Orchestrator知道您的复制集群的实际状态,但并不知道它们应当的状态。Orchestrator不知道一个独立的服务器应该归属于哪个集群;不知道当前primary与应用程序的预期是否匹配;也不知道用户是否打算创建一个多primary结构。它在设计上是通用的,允许社区定义任意拓扑结构。
旧的Vitess-Orchestrator集成
过去几年,Orchestrator是Vitess的外部实体。两者通过少量的API调用协作,Orchestrator并不具备Vitess的专属数据,许多整合都通过恢复前后钩子、shell脚本和API调用完成。这导致了一些竞争式的故障转移现象,或者某些操作彼此不可见,从而引发混乱。集群可能处于分裂状态或双primary状态。单个事件的丢失可能造成集群数据损坏。
在Vitess中的一级公民角色
最近,我们正式将Orchestrator集成到了Vitess,使其成为Vitess基础设施的重要组成部分。这是一个Vitess专属分支,Orchestrator能够理解Vitess原生功能,例如锁定分片或获取Tablet信息。
这一整合使Orchestrator同时具备集群意识和目标驱动能力。
集群意识
MySQL本身没有复制集群的概念(与InnoDB Cluster或MySQL Cluster不同):服务器只是互相复制,MySQL不会关心它们是否应该互相复制,或者复制树的整体健康状态。而Orchestrator可以基于它所见观察和评估复制树的状态。但Vitess对集群状态有确定判断。在Vitess中,每个MySQL服务器都有自己的vttablet(一个类似代理的角色)。tablet知道MySQL服务器的具体身份:它包含哪些schemas;属哪个分片;承担什么角色(primary、replica、OLAP等)。集成的Orchestrator现在直接从Vitess的拓扑服务中获取所有MySQL元数据。它不仅仅是因为连接关系得知两个服务器属于同一集群,而是通过Vitess提供的元数据明确知道这一点。Orchestrator可以观察到一个独立的服务器,并判定它确实属于某个集群。
目标驱动
这种集群意识从根本上改变了Orchestrator的方法,使其能够以目标驱动的方式操作。Orchestrator的目标是确保集群始终处于Vitess期望的状态。这是通过引入新检测模式和恢复方法实现的,这在其他情况下过于倾向化而无法实现。
一些示例:
- Orchestrator发现一个独立服务器。根据Vitess的拓扑服务,该服务器标记为REPLICA。Orchestrator将其诊断为“一个没有primary的replica”,并在验证GTID支持操作后,将其连接到合适的复制集群。
- Orchestrator发现一个可写的REPLICA,而Vitess不支持此设置。Orchestrator将其设为只读。
- 同样,Orchestrator发现一个处于只读状态的primary。它将其改为可写。
- Orchestrator检测到一个多primary设置(循环复制结构)。Vitess严格禁止这种设置。Orchestrator与拓扑服务确认哪一个才是真正的primary,然后将其他的primary转为标准replica。需要强调的是,多primary设置被认为是一种故障场景。
- 最有趣的场景是:Orchestrator发现一个完全工作正常的复制树,带有一个可写primary和只读replica,但Vitess认为primary应该是某个replica,而当前的primary应该是一个replica。这可能是由先前不完整的故障转移操作导致的。在这种情况下,Orchestrator将执行一个优雅接管(Vitess术语中称为计划重新主控),实际提拔正确的服务器为新的primary,同时降级“冒充者”primary。
因此,Vitess对集群应该的状态有明确的定义,而Orchestrator是执行该状态的操作员。值得注意的是,Orchestrator的操作要么会失败,要么最终会收敛到期望的状态。
那么,如果primary意外宕机,该提拔哪个服务器?
Orchestrator的提拔逻辑
在意外故障情况下,Orchestrator的任务是选取和提拔最合适的服务器,并将其身份更新到Vitess。新的交互确保了这一过程是收敛的,Orchestrator和Vitess不会出现对primary身份的冲突。
Orchestrator基于多个限制因素选取用于提拔的服务器,例如:
- 服务器是否配置为可以作为primary,例如是否启用了二进制日志?
- 它的版本是否与其他replica匹配?
- Vitess提供的关于特定主机的一般推荐信息(从元数据中获取)。
另外还有一些非服务器特定的一般规则决定了哪些提拔是可行的。比如:
- 我们是否严格要求只在同一数据中心内进行故障转移?
- 同一区域/可用区内?
- 或者,则严格要求只在数据中心外进行故障转移?
- 是否只针对配置为半同步replica的服务器进行故障转移?
提拔后的集群如何重新配置?
此前,这些问题有些通过配置变量解答,有些依赖用户基础设施。而新的整合允许用户选择故障转移和恢复策略,可通过代码定义。Orchestrator和Vitess目前已支持三种预配置模式,同时允许用户在规则范围内定义任何自定义策略。
更多内容将在后续文章中详细探讨。
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:http://www.choupangxia.com/2025/05/17/orchestrator-vitess/