Github utilise une base de données MySQL comme magasin de données pour toutes les transactions non-git
. La disponibilité de la base de données est essentielle au bon fonctionnement de Github. Le site Web Github lui-même, l'API Github, le service d'authentification, etc. doivent tous accéder à la base de données. Github exécute plusieurs clusters de bases de données pour prendre en charge différentes tâches de service. L'architecture de la base de données adopte une structure maître-esclave traditionnelle. Un nœud (base de données maître) du cluster prend en charge l'accès en écriture, et les nœuds restants (bases de données esclaves) synchronisent les modifications apportées à la base de données maître et prennent en charge les services de lecture. git
事务的数据存储。数据库的可用性对 Github 的正常运行而言至关重要。无论是 Github 网站本身,还是 Github API,身份验证服务等都需要访问数据库。Github 运行了多个数据库集群用于支撑不同的服务于任务。数据库的架构采用的是传统的主从结构,集群中一个节点(主库)支持写访问,其余的节点(从库)同步主库的变更,支持读服务。
主库的可用性至关重要。一旦主库宕机,集群将不能够支持数据写入服务:任何需要保存的数据都无法写入到数据库保存。最终导致 Github 上任何变更,例如代码提交,提问,用户创建,代码 review,创建仓库等操作都无法完成。
为了保证业务的正常运行,我们自然需要在集群中有一个可用的支持写入的数据库节点。同时,我们也必须能够快速的发现可用的可写入服务数据库节点。
就是说,在异常情况下,假如主库宕机的场景,我们必须确保新的主库能够立刻上线支持服务,同时保证集群中其他节点能够快速识别到新的主库。故障检测,主库迁移以及集群其他数据节点识别新主库的总时间构成了服务中断的总时间。
这篇文章说明了 GitHub 的 MySQL 高可用性和主库服务发现解决方案,该解决方案使我们能够可靠地运行跨数据中心的操作,能够容忍数据中心的隔离,并缩短在出现故障时停机时间。
本篇文章描述的解决方案是在以前 Github 高可用方案上的改进版本。正如前面说到的一样,MySQL 的高可用策略必须适应业务的变化。我们期望 MySQL 以及 GitHub 上其他的服务都有能够应对变化的高可用解决方案。
当设计高可用以及服务发现系统方案的时候,从下面几个问题出发,也许能够帮助我们快速找到合适的解决方案:
为了说明上面的几个问题,我们先来看一下我们之前的高可用方案,以及我们为什么要改进它。
在之前的方案中,应用了下面的技术方案:
客户端通过节点名称,例如 mysql-writer-1.github.net
,解析成主节点的虚拟 IP 地址 (VIP),从而找到主节点。
因此,正常情况下,客户端可以通过对节点名称的解析,连接到对应 IP 的主节点上。
考虑夸三个数据中心的拓扑结构的情况:
一旦主库异常,必须将其中的一个数据副本服务器更新为主库服务器。
orchestrator
La disponibilité de la bibliothèque principale est cruciale. Une fois la base de données principale en panne, le cluster ne sera plus en mesure de prendre en charge les services d'écriture de données : les données devant être enregistrées ne pourront pas être écrites dans la base de données pour être stockées. Par conséquent, toute modification sur Github, telle que la soumission de code, les questions, la création d'utilisateurs, la révision de code, la création d'entrepôt, etc., ne peut pas être effectuée.
mysql-writer-1.github.net
, dans l'adresse IP virtuelle (VIP) du nœud maître. 🎜🎜Par conséquent, dans des circonstances normales, le client peut se connecter au nœud maître de l'IP correspondante en analysant le nom du nœud. 🎜🎜Considérons le cas de la topologie de trois centres de données : 🎜🎜🎜🎜Une fois que la base de données principale est anormale, l'un des serveurs de réplique de données doit être mis à jour vers le serveur de base de données principal. 🎜🎜orchestrator
détectera les anomalies, sélectionnera une nouvelle base de données principale, puis réattribuera le nom de la base de données et l'adresse IP virtuelle (VIP). Le client lui-même ne connaît pas les modifications apportées à la bibliothèque principale. Les informations dont dispose le client sont uniquement le 🎜nom🎜 de la bibliothèque principale, ce nom doit donc pouvoir être résolu sur le nouveau serveur de bibliothèque principale. Considérez ce qui suit : 🎜🎜VIP doit être négocié : l'adresse IP virtuelle est détenue par la base de données elle-même. Le serveur doit envoyer une requête ARP pour occuper ou libérer le VIP. Avant que la nouvelle base de données puisse allouer de nouveaux VIP, l'ancien serveur doit d'abord libérer les VIP qu'il détient. Ce processus entraînera des problèmes inhabituels :🎜Lorsque nous installons réellement le VIP, le VIP est également lié par l'emplacement physique réel. Cela dépend principalement de l'emplacement du commutateur ou du routeur. Par conséquent, nous ne pouvons réattribuer le VIP que sur le même serveur local. En particulier, il existe des cas où nous ne pouvons pas attribuer de VIP aux serveurs d'autres centres de données et devons apporter des modifications DNS.
Ces limitations à elles seules suffisent à nous pousser à trouver de nouvelles solutions, mais voici les éléments à considérer :
Le serveur maître utilise le service pt-heartbeat
pour s'auto-injecter les battements de coeur d'accès à des fins de Mesure de la latence et contrôle de limitation. Le service doit être démarré sur le nouveau serveur principal. Si possible, le service de l'ancien serveur principal sera arrêté lors du remplacement du serveur principal. pt-heartbeat
服务去自注入访问心跳,目的是延迟测量和节流控制。该服务必须在新的主服务器开始。如果可以,在更换主服务器的同时会关闭旧的主服务器这项服务。
同样地,Pseudo-GTID 是由服务器自行管理的。它需要在新的主服务器开始,最好在旧的主服务器上停止。
新的主服务器将设置为可写入。如果可以的话,旧的主服务器将设置为 read_only
(只读)。
这些额外的步骤是导致总停机时间的一个因素,并引入了它们自己的故障和摩擦。
解决方案是有效的,GitHub 已经成功地进行了 MySQL 故障转移,但是我们希望 HA 在以下方面有所改进:
新策略可以改进,解决或者优化上面提到的问题。现在高可用的组成如下:
anycast
作为网络路由。新的结构移除了 VIP 和 DNS 。在引入更多的组件的同时,我们能够解藕这些组件,并且简化相关的任务,并易于利用可靠稳定的解决方案。详情如下。
正常情况,应用通过 GLB/HAProxy 连接到写入节点。
应用感知不到 master 身份。之前,都是使用名称。例如 cluster1
的 master 是 mysql-writer-1.github.net
。现在的结构中,这个名称被 anycast IP 取代。
通过 anycast
,名称被相同的 IP 取代,但流量由客户端的位置来进行路由。特别的,当数据中心有 GLB 时,高可用负载均衡器部署在不同的盒子内。 通向 mysql-writer-1.github.net
read_only
si possible. 🎜🎜🎜🎜Ces étapes supplémentaires sont un facteur de temps d'arrêt total et introduisent leurs propres problèmes et frictions. 🎜🎜La solution fonctionne, GitHub a effectué avec succès le basculement MySQL, mais nous aimerions que HA s'améliore dans les domaines suivants : 🎜🎜🎜Agnostique du centre de données. 🎜🎜Tolérant aux pannes du centre de données. 🎜🎜Supprimez les flux de travail de collaboration peu fiables. 🎜🎜Réduisez les temps d’arrêt totaux. 🎜🎜Dans la mesure du possible, effectuez un basculement sans perte. 🎜🎜anycast
en tant que réseau routeur. 🎜🎜🎜🎜🎜 La nouvelle structure supprime VIP et DNS. Au fur et à mesure que nous introduisons davantage de composants, nous sommes en mesure de les découpler, de simplifier les tâches associées et de faciliter l'exploitation d'une solution fiable et stable. Détails ci-dessous. 🎜cluster1
est mysql-writer-1.github.net
. Dans la structure actuelle, ce nom est remplacé par anycast IP. 🎜🎜Avec anycast
, le nom est remplacé par la même IP, mais le trafic est acheminé par la localisation du client. En particulier, lorsque le data center dispose de GLB, l’équilibreur de charge haute disponibilité est déployé dans un boîtier différent. Le trafic vers mysql-writer-1.github.net
est dirigé vers le cluster GLB dans le centre de données local. De cette façon, tous les clients sont servis par le proxy local. 🎜Utilisez GLB sur HAProxy. HAProxy dispose de pools d'écriture : un pour chaque cluster MySQL. Chaque pool dispose d'un service backend : le nœud maître du cluster. Tous les boîtiers GLB/HAProxy du data center ont le même pool, ce qui signifie que ces pools correspondent aux mêmes services backend. Ainsi, si l'application s'attend à écrire mysql-writer-1.github.net
, elle ne se soucie pas du service GLB auquel se connecter. Cela mènera au nœud maître cluster1
réel. mysql-writer-1.github.net
,不同关心连接哪个 GLB 服务。它会导向实际的 cluster1
master 节点。
就应用连接 GLB ,发现服务而言,不需要重新发现。GLB 负责全部流量导向正确的目的地。
GLB 是怎么知道哪些服务是后端,以及如何告知 GLB 变化的呢?
Consul 以服务发现解决方案而闻名,也提供 DNS 服务。 然而,在我们的解决方案中,我们将其用作高度可用的键值 (KV) 存储。
在 Consul 的 KV 存储中,我们写入集群主节点的身份。 对于每个集群,都有一组 KV 条目指示集群的主设备 fqdn
、端口、ipv4、ipv6。
每个 GLB/HAProxy 节点都运行 consul-template:一个监听 Consul 数据变化的服务(在我们的例子中:集群主数据的变化)。 consul-template
生成一个有效的配置文件,并且能够在配置更改时重新加载 HAProxy。
因此,每个 GLB/HAProxy 机器都会观察到 Consul 对 master 身份的更改,然后它会重新配置自己,将新的 master 设置为集群后端池中的单个实体,并重新加载以反映这些更改。
在 GitHub,我们在每个数据中心都有一个 Consul 设置,并且每个设置都是高度可用的。 但是,这些设置彼此独立。 它们不会在彼此之间复制,也不会共享任何数据。
Consul 如何获知变化,信息如何跨 DC 分发?
我们运行一个 orchestrator/raft
设置: orchestrator
节点通过 raft 机制相互通信。 每个数据中心有一个或两个 orchestrator
节点。
orchestrator
负责故障检测和 MySQL 故障切换,以及将 master 的变更传达给 Consul 。 故障切换由单个 orchestrator/raft
leader 节点操作,但是集群现在拥有新 master 的消息通过 raft
机制传播到所有 orchestrator
节点。
当 orchestrator
节点收到 master 变更的消息时,它们各自与本地 Consul 设置通信:它们各自调用 KV 写入。 具有多个 orchestrator
代理的 DC 将多次(相同)写入 Consul。
在 master 崩溃的情况下:
orchestrator
节点检测故障.orchestrator/raft
leader 节点开始恢复,一个数据服务器被更新为 master 。orchestrator/raft
公告所有 raft
子集群节点变更了 master 。orchestrator/raft
成员收到一个 leader 节点 变更的通知。它们每个成员都把新的 master 更新到本地 Consul
KV 存储中。consul-template
,该模版观察 Consul
KV 存储中的更改,并重新配置和重新加载 HAProxy。每个组件都有明确的责任归属,整个设计既是解耦的,又是简化的。orchestrator
不知道负载平衡器。 Consul
不需要知道消息的来源。代理只关心 Consul
fqdn
maître du cluster, le port, l'ipv4, l'ipv6. consul-template
génère un fichier de configuration valide et la possibilité de recharger HAProxy lorsque la configuration change.
orchestrator
. 🎜🎜orchestrator
est responsable de la détection des pannes et du basculement MySQL, ainsi que de la communication des modifications de 🎜master🎜 à 🎜Consul🎜. Le basculement est opéré par un seul nœud leader orchestrator/raft
, mais le message indiquant que le cluster a désormais un nouveau 🎜master🎜 est propagé à tous les nœuds orchestrator
via le mécanisme de radeau
. 🎜🎜Lorsque les nœuds orchestrator
reçoivent le message du changement 🎜master🎜, ils communiquent chacun avec la configuration 🎜Consul🎜 locale : ils appellent chacun KV write. Un DC avec plusieurs agents orchestrator
écrira plusieurs fois (identiques) à 🎜Consul🎜. 🎜orchestrator
Échec de détection du nœud.🎜🎜orchestrator/raft
Le le nœud leader commence à récupérer et un serveur de données est mis à jour pour devenir le maître. 🎜🎜orchestrator/raft
annonce que tous les nœuds du sous-cluster raft
ont changé de maître. 🎜🎜Chaque membre orchestre/radeau
reçoit une notification de changement de nœud leader. Chacun de leurs membres met à jour le nouveau maître dans le magasin KV Consul
local. 🎜🎜Chaque GLB/HAProxy exécute consul-template
, qui observe les changements dans le magasin KV Consul
et reconfigure et recharge HAProxy. 🎜🎜Le trafic client est redirigé vers le nouveau maître. 🎜🎜🎜Chaque composant a une responsabilité claire, et l'ensemble de la conception est à la fois découplé et simplifié. orchestrator
ne connaît pas les équilibreurs de charge. Consul
n'a pas besoin de connaître la source du message. L'agent ne se soucie que du Consul
. Le client ne se soucie que du proxy. 🎜🎜Aussi : 🎜🎜🎜Aucune modification DNS à propager🎜🎜Pas de TTL. 🎜🎜Le stream ne coopère pas avec le maître défaillant, il est largement ignoré. 🎜🎜🎜🎜Détails supplémentaires🎜🎜🎜Pour protéger davantage votre trafic, nous avons ce qui suit : 🎜hard-stop-after
très court. Lorsqu'il recharge le nouveau serveur principal dans le pool d'écriture, il met automatiquement fin à toutes les connexions existantes à l'ancien serveur maître. hard-stop-after
。当它重新加载写入器池中的新后端服务器时,它会自动终止与旧主服务器的任何现有连接。hard-stop-after
,我们甚至不需要客户的合作,这减轻了脑裂的情况。值得注意的是,这不是封闭的,并且在我们终止旧连接之前一段时间过去了。但是在某个时间点之后,我们会感到很舒服,并且不会期待任何令人讨厌的惊喜。我们将在以下部分进一步解决问题并追求 HA 目标。
orchestrator
使用 整体方法 来检测故障,因此非常可靠。我们没有观察到误报:我们没有过早的故障转移,因此不会遭受不必要的停机时间。
orchestrator/raft
进一步解决了完整的 DC 网络隔离(又名 DC 围栏)的情况。 DC 网络隔离可能会导致混乱:该 DC 内的服务器可以相互通信。是它们与其他 DC 网络隔离,还是其他 DC 被网络隔离?
在 orchestrator/raft
设置中,raft
领导节点是运行故障转移的节点。领导者是获得组中大多数人(法定人数)支持的节点。我们的协调器节点部署是这样的,没有一个数据中心占多数,任何 n-1 数据中心都可以。
在 DC 网络完全隔离的情况下,该 DC 中的 orchestrator
节点会与其他 DC 中的对等节点断开连接。因此,孤立 DC 中的 orchestrator
节点不能成为 raft
集群的领导者。如果任何这样的节点恰好是领导者,它就会下台。将从任何其他 DC 中分配新的领导者。该领导者将得到所有其他能够相互通信的 DC 的支持。
因此,发号施令的 orchestrator
节点将是网络隔离数据中心之外的节点。如果一个独立的 DC 中有一个主控,orchestrator
将启动故障转移,用其中一个可用 DC 中的服务器替换它。我们通过将决策委托给非隔离 DC 中的法定人数来缓解 DC 隔离。
通过更快地公布主要更改可以进一步减少总停机时间。如何实现这一点?
当 orchestrator
开始故障转移时,它观察可用于提升的服务器队列。理解复制规则并遵守提示和限制,它能够对最佳操作过程做出有根据的决策。
它可能认识到,一个可用于促销的服务器也是一个理想的候选人,例如:
在这种情况下, orchestrator
hard-stop-after
, nous n'avons même pas besoin de la coopération du client, ce qui atténue les situations de division cérébrale. Il convient de noter que celle-ci n'est pas fermée et qu'un certain temps s'écoule avant que nous ne mettions fin à l'ancienne connexion. Mais passé un certain point, on se sent à l’aise et on ne s’attend pas à de mauvaises surprises. Nous n'exigeons pas strictement que le consul soit de garde à tout moment. En fait, nous avons seulement besoin qu’il soit disponible en cas de basculement. Si Consul échoue, GLB continuera à fonctionner en utilisant les dernières valeurs connues et ne prendra pas de mesures drastiques.
GLB est configuré pour vérifier l'identité du maître nouvellement promu. Semblable à notre pool MySQL contextuelorchestrator
Utilise une approche holistique 🎜 pour détecter les pannes et est donc très fiable . Nous n’avons observé aucun faux positif : nous n’avons eu aucun basculement prématuré et n’avons donc pas subi de temps d’arrêt inutiles. 🎜🎜orchestrator/raft
aborde en outre le cas de l'isolation complète du réseau DC (c'est-à-dire la clôture DC). L'isolation du réseau DC peut prêter à confusion : les serveurs de ce DC peuvent communiquer entre eux. Le réseau d'autres DC est-il isolé des autres contrôleurs de domaine, ou le réseau des autres contrôleurs de domaine est-il isolé ? 🎜🎜Dans une configuration orchestrator/raft
, le nœud leader raft
est le nœud qui exécute le basculement. Le leader est le nœud qui bénéficie du soutien de la majorité du groupe (le quorum). Le déploiement de notre nœud de coordination est tel qu'aucun centre de données n'a la majorité, n'importe quel centre de données n-1 fera l'affaire. 🎜🎜Lorsque le réseau DC est complètement isolé, le nœud orchestrator
du DC sera déconnecté des nœuds homologues des autres DC. Par conséquent, le nœud orchestrator
dans un contrôleur de domaine orphelin ne peut pas devenir le leader du cluster raft
. Si l’un de ces nœuds devient le leader, il se retirera. Un nouveau leader sera assigné à partir de n'importe quel autre DC. Ce leader sera soutenu par tous les autres DC pouvant communiquer entre eux. 🎜🎜Par conséquent, le nœud orchestrateur
donnant les ordres sera un nœud extérieur au data center d'isolation du réseau. S'il y a un maître dans un DC autonome, orchestrator
lancera un basculement, en le remplaçant par un serveur de l'un des DC disponibles. Nous atténuons l'isolement du DC en déléguant les décisions à un quorum dans un DC non isolé. 🎜orchestrator
démarre un basculement, il observe la file d'attente des serveurs disponibles pour la promotion. Comprendre les règles de réplication et respecter les conseils et les limites vous permet de prendre des décisions éclairées sur la meilleure marche à suivre. 🎜🎜On peut reconnaître qu'un serveur disponible en promotion est aussi un candidat idéal, par exemple : 🎜🎜🎜Rien n'empêche la mise à niveau du serveur (l'utilisateur a peut-être laissé entendre qu'un tel serveur est la mise à niveau privilégiée), et 🎜Un serveur devrait pouvoir avoir tous ses frères et sœurs comme répliques. 🎜Dans ce cas, orchestrator
définit d'abord le serveur comme accessible en écriture, puis annonce immédiatement la promotion du serveur (dans notre cas, en écrivant au magasin Consul KV), même si la réparation de l'arbre de réplication démarre de manière asynchrone, cette opération prend généralement plusieurs secondes. 🎜🎜Il est probable que l'arborescence de réplication soit intacte avant que le serveur GLB ne soit complètement rechargé, mais ce n'est pas strictement obligatoire. Le serveur accepte très bien les écritures ! 🎜🎜🎜Réplication semi-synchrone🎜🎜🎜Dans la 🎜réplication semi-synchrone🎜 de MySQL, le maître n'accuse pas les validations de transaction tant que les modifications ne sont pas connues comme ayant été envoyées à une ou plusieurs répliques. Il fournit un moyen d'obtenir un basculement sans perte : toutes les modifications appliquées au serveur principal sont soit appliquées au serveur principal, soit attendent d'être appliquées à l'une des répliques. 🎜La cohérence a un coût : le risque de disponibilité. Si aucune réplique n'accuse réception des modifications, le maître bloque et arrête l'écriture. Heureusement, il existe une configuration de délai d'attente après laquelle le maître peut revenir en mode de réplication asynchrone, rendant ainsi les écritures à nouveau disponibles.
Nous avons fixé le délai d'attente à une valeur raisonnablement basse : 500ms
. Il suffit d’envoyer les modifications de la réplique principale du DC à la réplique DC locale ainsi qu’au DC distant. Avec ce timeout, nous pouvons observer un comportement semi-synchrone parfait (pas de repli vers la réplication asynchrone) et pouvons facilement utiliser des périodes de blocage très courtes en cas d'échec d'acquittement. 500ms
。将更改从主 DC 副本发送到本地 DC 副本,通常也发送到远程 DC,这已经足够了。通过这个超时,我们可以观察到完美的半同步行为 (没有退回到异步复制) ,并且在确认失败的情况下可以很轻松地使用非常短的阻塞周期。
我们在本地 DC 副本上启用半同步,在主服务器死亡的情况下,我们期望 (尽管不严格执行) 无损故障转移。完全直流故障的无损故障转移是昂贵的,我们并不期望它。
在尝试半同步超时的同时,我们还观察到了一个对我们有利的行为:在主要失败的情况下,我们能够影响理想候选对象的身份。通过在指定的服务器上启用半同步,并将它们标记为候选服务器,我们能够通过影响故障的结果来减少总停机时间。在我们的实验中,我们观察到我们通常最终会得到理想的候选对象,从而快速地广而告之。
我们没有在升级 / 降级的主机上管理 pt-heart
服务的启动 / 关闭,而是选择在任何时候在任何地方运行它。这需要进行一些修补,以便使 pt-heart 能够适应服务器来回更改 read_only
(只读状态) 或完全崩溃的情况。
在我们当前的设置中,pt-heart
服务在主服务器和副本上运行。在主机上,它们生成心跳事件。在副本上,他们识别服务器是 read_only
(只读) 的,并定期重新检查它们的状态。一旦服务器被提升为主服务器,该服务器上的 pt-heart
就会将服务器标识为可写的,并开始注入心跳事件。
我们进一步 orchestrator:
read_only
。在所有的新 master 的基础上,这减少了摩擦。一个刚刚被提升的 master 显然应该是有生命力,并且可以被接受的,否则我们不会提升它。因此,让 orchestrator
直接讲更改应用于提升的 msater 是有意义的。
我们进一步 orchestrator:
read_only
。在所有的新 master 的基础上,这减少了摩擦。一个刚刚被提升的 master 显然应该是有活力,并且可以被接受的,否则我们不会提升它。因此,让 orchestrator
Inject heartbeat
Nous ne gérons pas le démarrage/arrêt du servicept-heart
sur l'hôte mis à niveau/déclassé, mais choisissons de le faire n'importe où à à tout moment, exécutez-le. Cela nécessite quelques patch pour activer pt-heart S'adapte aux situations où le serveur passe d'avant en arrière en read_only
(état de lecture seule) ou plante complètement. Dans notre configuration actuelle, le service pt-heart
s'exécute sur le maître et les réplicas. Sur l'hôte, ils génèrent des événements de battement de cœur. Sur les répliques, ils identifient les serveurs comme read_only
et revérifient périodiquement leur état. Une fois qu'un serveur est promu maître, pt-heart
sur ce serveur identifie le serveur comme étant accessible en écriture et commence à injecter des événements de battement de cœur.
Délégation de propriété de l'orchestrateur
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!