千家信息网

GitHub的MySQL高可用怎么解决

发表于:2025-02-08 作者:千家信息网编辑
千家信息网最后更新 2025年02月08日,本篇内容主要讲解"GitHub的MySQL高可用怎么解决",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"GitHub的MySQL高可用怎么解决"吧!引言Gi
千家信息网最后更新 2025年02月08日GitHub的MySQL高可用怎么解决

本篇内容主要讲解"GitHub的MySQL高可用怎么解决",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"GitHub的MySQL高可用怎么解决"吧!

引言

GitHub在所有非Git的地方使用MySQL存储数据,其可用性对GitHub的运行至关重要。网站,API,鉴权等等,都需要数据库访问。GitHub运行多个MySQL集群来满足其不同的服务和任务。这些集群使用典型的主复结构,在集群中只有唯一节点(主)能写入,其他节点(复制点)异步地复制主节点的变化(重播)并提供【读】服务。

主节点的可用性至关重要。没有了主节点,整个集群都不能写入了(数据保存不下来)。任何数据变化操作,如提交、Bug、注册、新建库等等,都将失败。要能写入显然需要有一个可获得的写入节点,即主节点。其中关键是,我们能定位或者发现这个节点。

在主节点崩溃的情形,必须保证一个新的主节点出现,并且快速地广播出去。检测到崩溃,主节点切换和集群广播告知,一起合计的时间就是总宕机时间。当然越小越好!

本文展示了GitHub的MySQL高可用和集群选主解决方案,该方案让GitHub可靠地运行跨数据中心操作,容忍数据中心隔离(不可用),实现更短的宕机时间。

高可用目标
本文描述的解决方案是之前GitHub实现的高可用的迭代优化。当扩容的时候,MySQL的高可用能够适应变化。我们也期望在GitHub有类似MySQL的策略用于其他服务。

当考虑高可用和服务发现时,一些问题会引导你走向一个合适解决方案,不完全的问题清单如下:

  • 能忍受多久的宕机时间?

  • 崩溃检测是否可靠?能否忍受错误(过早切换)?

  • 失效切换是否可靠?那里失效了?

  • 方案在跨中心时是否也工作良好?在高/低延迟的网络里呢?

  • 方案能否容忍整个数据中心崩溃或网络隔离?

  • 是否有机制组织或减缓脑裂出现(集群中两个节点都声称自己是主,两者独立互,不知道对方,并都接受写入)?

  • 能否承受数据丢失?丢多少能忍?

为了说明这些问题,让我们看看以前的高可用解决方案,并且为何要优化它!

丢弃基于VIP和DNS的发现策略

在以前的迭代中,我们使用:

  • orchestrator做崩溃检测和失效切换,并

  • 用VIP和DNS做主节点发现 在该策略下,客户端用名字来发现写节点,例如mysql-writer-1.github.net,该名字被解析到一个虚拟IP地址(VIP),对应的主节点主机就能访问到。因此,正常情况下,客户端会解释这个名字,连到获得的IP,找到主节点。

考虑这样的复制拓扑结构,跨了3个数据中心: 在主节点失效时,复制节点里的一个 ,必须被提名替代其【主】位。

orchestrator将检测失效,提名新主,接着重新定义名字或VIP。客户端并不知道新主怎么定位,因为他们只知道名字,而名字必须解释到新主上。情况是这样的:

VIP是协同的:他们被数据库服务器声称并拥有。为了获得或释放一个VIP,服务器必须发送一个ARP请求。占用该VIP的服务器必须先释放才能让新主获得它。这隐含的效果是:

  • 一个有序的失效切换操作先得联系失效旧主并请求它释放VIP,接着联系新主请求其抓住该VIP。假如旧主无法访问了或者拒绝释放VIP咋办?在旧主失效情景里,它不能按时响应或完全不响应,都是可能的。

    • 容许脑裂可以解决该问题:两个主机都生成拥有同一个VIP。不同的客户端可能连到其中之一上,看在网络上谁离的近。

    • 其中根源在于两个独立的服务器需要协作,而这个结构是不可靠的。

  • 就算旧主做出协作了,整个流程也浪费了宝贵的时间:切换到新主必须等到能联系到旧主。

  • 而且当VIP改变了,已存在的客户端连接也不能保证从旧主哪里断开,仍然会出现事实上的脑裂情景。

VIP通常是以物理位置边界来设计,由路由器或开关拥有。因而,我们只能给相关位置的服务器重设VIP。在一些特殊情况下,我们无法给另一个数据中心的新主重设VIP,必须修改DNS。

DNS的变化扩散出去需要更长时间。客户端缓存了DNS(特定时间后才刷新)。跨数据中心的失效通常导致更长的宕机时间:需要更多时间让客户端意识到主节点变了。

这些限制促使我们寻求更好的解决方案,更多地考虑:

  • 主节点通过pt-heartbeat心跳服务来自主地注入自己,基于延迟度量和流量控制。该服务必须在新提名的主节点上被启动。如果可能,在旧主上的该服务将被关停。

  • 类似的,Pseudo-GTID注入由主节点自主管理。它应该在新主启动,并最好在旧主关停。

  • 新主被置为可写入,旧主被置为只读(如果可能)。

这些额外的步骤会增加更多的总宕机时间,并且他们自身也会遇到失败和冲突。这个解决方案是有效的,GitHub也做过成功的失效切换,在雷达监控下运行良好。但我们希望高可用在这些方面做得更好:

  • 跨数据中心无感。

  • 能忍受数据中心失效。

  • 去除不可靠的协作流程。

  • 减少总宕机时间。

  • 尽可能做到无损失效切换。

GitHub高可用解决方案:orchestrator,Consul,GLB

我们的新策略,伴随着附带的优化,上述关注问题的解决或减轻。当前的HA结构中包括:

  • orchestrator负责失效探测和切换(用的是跨数据中心的orchestrator/raft)。

  • Hashicorp的Consul用于服务发现。

  • GLB/HAProxy作为代理层处于客户端和写节点之间。

  • anycast用于网络路由。

新的结构去掉了VIP和DNS修改。虽然我们引入了更多的组件,但能够解耦组件并简化任务,也能利用上坚固稳定的解决方案。接下来详细的说明下。

一个正常流程

正常情况下,应用通过GLB/HAProxy连接到写节点,应用永远感受不到主节点身份。在以前,应用需要使用名字。例如,cluster1集群的主节点用mysql-writer-1.github.net。在当前的结构下,这个名字会被解释到一个anycast地址(IP)。

用anycast,这个名字解释到任何地方的同一个IP,但流量会基于客户端位置被路由到不同地方。尤其是,我们的每一个数据中心都有GLB,我们的高可用负载均衡器,部署在多个机柜里。去往mysql-writer-1.github.net的流量总是路由到本地数据中心的GLB集群。

因而,所有的客户端都由本地的代理服务。GLB运行于HAProxy之上。HXProxy有写节点池:每个MySQL集群有这么个池,每个池仅只一个后端服务器 - 集群主节点。所有数据中心的GLB/HAProxy机柜用同一个池,亦即用池里的同一个后端服务器。因而,应用如果想写入到mysql-writer-1.github.net,和其所连接到的GLB服务器无关,它总是被路由到cluster1集群的主节点。

应用只需了解,发现终结于GLB,不存在重新发现的必要。剩下的就由GLB负责把流量路由到正确的目的地。那么GLB怎么知道服务于那些后台服务器,并且怎么扩散对GLB的修改呢?
用Consul发现

Consul是众所周知的服务发现解决方案,也提供DNS服务。在我们的方案里,使用它作为高可用的KV存储。

在Consul的KV存储里存放集群主节点的标识。对每个集群,有一组KV条目标识集群主节点的fqdn、port、ipv4和ipv6。

每个GLB/HAProxy节点运行着consul-template:一个监听Consul数据变化的服务(对我们来说就是对集群描述数据的变化),该服务产生一个合法配置文件能用于重载HAProxy(当配置变化时)。

因而,Consul里一个主节点标识的变化被每个GLB/HAProxy机柜跟踪着,并对自己进行重新配置,将新主设为集群后台服务器池里唯一实体,并重载以反映这些变化。

在GitHub我们每个数据中心都有一个Consul,都是高可用结构。但这些结构是互相独立的,不互联复制也不共享任何数据。

那么Consul怎么获知变化?以及信息怎么在跨数据中心间传递的?
orchestrator/raft

我们运行着一个orchestrator/raft结构:orchestrator节点间通过raft互联交流。每个数据中心有1-2个orchestrator节点。

orchestrator负责失效检测,MySQL失效切换,以及Consul里主节点信息变化的传递。失效切换由单一的orchestrator/raft领头节点操作,但变化 - 集群有个新主的消息,被扩展到所有orchestrator节点,通过raft机制。

当orchestrator节点接收到新主变化的消息,他们与本地Consul交互:触发一个KV写操作。有多个orchestrator节点的数据中心可能触发多次对Consul的写入。

所有流程组合在一起

当主节点崩溃时:

  • orchestrator检测到失效。

  • orchestrator/raft领头节点触发一个恢复。一个新主被提名。

  • orchestrator/raft广播主节点变化给所有raft集群节点。

  • 每个orchestrator/raft节点收到领头节点变化通知,更新本地Consul的KV存储(新主的标识)。

  • 每个GLB/HAProxy的consul-template监听到Consul里KV值变化,随即重新配置并重载HAProxy。

  • 客户端流量转向新主。

流程中每个组件都有明确的功能,整个设计解耦得很好也相当简单。orchestrator不知道负载均衡,Consul不知道信息从哪儿来,HAProxy只关注Consul,而客户端只关注Proxies。而且:

  • 没有DNS变化需要扩展。

  • 没有TTL。

  • 流程不需要死旧主协作。

其他一些细节

为了让流程更加安全,我们还做了这些工作:

  • HAProxy配置很短的hard-stop-after。当其重载新的后台服务器到写节点池,它自动地终止所有对旧主的连接。

    • 用hard-stop-after参数我们不必寻求客户端的协作,从而减轻脑裂影响。当然这明显没有完全消除,我们断掉所有旧连接需要时间。但总算有个时间点,在那之后让我们感觉舒服并且不会有令人不爽的意外。

  • 我们不严格要求Consul在任何时候都可用。事实上,我们只需要它在失效切换时能用即可。如果Consul恰好不可用,GLB会接着用最后已知的信息完成操作,不会造成什么极端行为。

  • GLB被设置为校验新提名主节点的标识,类似我们的context-aware MySQL pools,会对后台服务器进行检查,确认其确实是个写入节点。如果我们不慎删除了Consul中的主节点标识,也没问题,空项会被忽略。如果我们不慎将非主服务器写到到Consul里,也没问题,GLB将拒绝更新它仍按旧状态继续运行。

我们继续追寻高可用的目标和关注。

orchestrator/raft失效检测

orchestrator用holistic approach来检测失效,这是很可靠的。我们没有观察到错误的失效切换,也就没有承担不必要的宕机时间。

orchestrator/raft更进一步深究完整的数据中心网络隔离的情形。该情形下会出现误导:数据中心里服务器能互相对话。但此时,是自己被其他数据中心隔离了,还是其他数据中心被隔离了?

在orchestrator/raft结构里,raft领头节点负责失效切换。领头节点是个被组里多数支持的节点(类似民主投票)。我们orchestrator节点部署单中心选主,而是任何n-1个中心来做。

在完整的数据中心网络隔离事件里,数据中心的orchestrator节点从其他节点(在其他数据中心的)断开连接。这样,隔离数据中心的orchestrator节点就不能成为raft集群的领头。如果任何这类节点不巧成为领头,它会宕掉。一个新的领头会从其他数据中心赋予,这个领头有其他数据中心的支持(投票),它有能力相互之间通信。

因而,这个orchestrator节点被叫做【枪击】,它是网络隔离数据中心外面来的。假设在隔离的数据中心里有个主节点,orchestrator会触发失效切换来替换它,用其他数据中心获得的服务器。我们缓解了数据中心隔离,通过委托其他非隔离的数据中心进行选主。

更快地扩展(广播)

总宕机时间能显著地降低,如果能更快地广播主节点变化。怎么做到呢?

当orchestrator开始失效切换,它观察可能被提名的众多服务器。通过提示或限制,理解复制规则和曾经记忆,它会依据合理程序做出科学的选择。

它认为可被提名的服务器是个理想候选者,依据:

  • 没有阻止该服务器被提名的任何障碍(或者用户潜在地提示该服务器是适合被提名),并且

  • 该服务器能被期待可以让它的兄弟节点作为复制节点。

满足条件下,orchestrator将其先设置为可写入,并立即广播该服务器提名(写入到Consul库里),同时异步地开始修复复制节点树,该操作通常需要花几秒钟时间。

等到我们的GLB服务器都完成重载,复制节点树也基本完成重整了,当然这并不是必须的。服务器恢复到可写入就算OK。

半同步复制

在MySQL里,半同步复制是主节点不确认一个事务的提交,直到数据变化已被传递到1个或多个复制从节点。该行为提供了一种达到无损失效切换的方法:任何主节点的变化都已在复制从节点上应用或正在应用。

一致性是有成本的:对可获得性造成风险。假设复制节点没给收到变化的确认,主节点会阻塞,写操作堆积。幸运的是,可以设置超时,超过时间就让主节点切回到异步复制模式,让写操作可以继续。

我们设置该超时时间在一个合理低值(500ms),这相对于将变化传递到本地DC的复制点的时间足够久,甚至够传递到远程DC的复制点。在这个超时时间内,我们观察到完美的半同步复制行为(没有跌落到异步复制),以及满意的短暂阻塞(当确认失败时)。

在本地DC复制点我们用半同步复制,在遇到主节点死亡,我们期待(不是绝对要求)无损的失效切换。无损的失效切换在一个整个DC失效中代价过于高昂,不是我们的诉求。

在实验半同步复制超时时,我们也观察到对我们有利的现象:在主节点失效时我们能够影响理想候选者的标识。通过在指定的服务器设置半同步复制,标识其作为候选者,我们能减少总宕机时间(通过影响失效结果)。在我们的实验中,我们观察到能更快完成候选者筛选,并因此加快新主广播。

心跳注入

相对于让pt-heartbeat服务在当选_落选的新主上启_停,我们选择让其在任何时间任何地点都运行着。这需要对pt-heartbeat打个补丁让其能够适应服务的读写状态变换,甚至完全宕机。

在当前配置中pt-heartbeat服务运行在主节点和复制点上。在主节点上,它产生心跳,在复制点上,它标识服务器为只读并定时循环地检查其状态。一旦某个服务器被提名为新主,其上的pt-heartbeat就标识其为可写入并且开始产生心跳。

orchestrator所有权委托

orchestrator承担了更多的工作:

  • Pseudo-GTID生成器。

  • 设置新主可写入状态,清除复制点状态。

  • 设置旧主只读状态(如果可能)。

这是为了减少新主各工作的冲突。新主被选出显然是期望它活着并可访问,否则我们就没必要提名它。当它能感知了,就让orchestrator将变化直接应用到它身上。

限制和缺陷

代理层让应用无法感知到主节点的标识,但他也让应用的标识被屏蔽在主节点之外。所有主节点看起来连接都都来自代理层,丢失了连接的真实来源信息。随着分布式系统前行,我们仍有些未处理到的情形。

尤其,在数据中心网络隔离情形,假设主节点是在被隔离DC里,而同DC的应用还能写入到主节点,而此时网络恢复了,这就可能导致状态不一致。我们正在探索降低脑裂后患的方法,通过实现一个可靠的STONITH,在正好隔离的DC里。像之前一样,将主节点关停需要点时间,这仍将存在短暂的脑裂期。完全避免脑裂的操作成本是相当高昂的。

更多的情形包括:Consul在失效切换时宕了;部分DC隔离,等等。我们明白在分布式系统里,堵上所有的漏洞是不可能的,所以我们专注于最重要的情形。

结果

我们的orchestrator_GLB_Consul架构实现了:

  • 可靠的失效检测;

  • 不可知数据中心失效切换;

  • 典型的无损失效切换;

  • 数据中心网络隔离支持;

  • 降低脑裂损害;

  • 没有协作延迟;

  • 大多数10-13秒左右的总宕机时间,少数要20秒,极端要25秒;

到此,相信大家对"GitHub的MySQL高可用怎么解决"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

节点 数据 服务 数据中心 服务器 变化 切换 集群 隔离 客户 方案 时间 客户端 旧主 标识 机时 结构 网络 应用 运行 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 如何查找云端服务器 云锁服务器怎么设置漏洞防护 荆州市中联软件开发有限公司 王牌战争服务器维护是什么意思 升腾服务器供应价格 重庆定制软件开发工程师 幼儿园网络安全工作情况 手机信息数据库下载吗 网络安全简单的画 最经济的数据库软件 基线管理服务器 全民飞机大战网络技术 围绕网络安全和普通话推普 windows连接服务器工具 没有网络主权就没有网络安全 坪山区数据网络技术开发服务标准 gene基因数据库的字母与数字 举办网络安全黑板报通知 服务器安全认证失败怎么解决 中新赛克校招软件开发待遇 网络安全保障体系有待进一步健全 rust服务器管理网页源码 mac下搭建服务器搭建 计算机网络技术以太网软件 web服务器网络安全 怎样复制数据库数据 服务器安全管理制度和操作规程 广州追尚网络技术有限公司 格力软件开发怎么样 怎么重新设置打印服务器ip
0