GitHub服务中断24小时11分钟事故分析报告\n

\"\"
上周,GitHub经历了一次事故,导致服务降级24小时11分钟。虽然平台的某些部分不受事故影响,但仍然有多个内部系统受到了影响,向用户显示了过时且不一致的内容。所幸没有用户数据丢失,但针对几秒钟数据库写入的手动调整工作仍在进行当中。在发生事故期间,Webhook无法提供服务,也无法构建和发布GitHub Pages。

我们对每个受影响的用户深表歉意。我们深切感受到用户对GitHub的信任,并为构建能够保持平台高可用性的弹性系统而感到自豪。在这次事故中,我们让用户失望了,我们深感抱歉。虽然我们无法撤销导致GitHub平台长时间无法使用的问题,但我们可以解释导致这次事故的原因、我们从中吸取的教训以及我们将要采取的措施,以便确保类似情况不会再次发生。

背景

大多数面向用户的GitHub服务都运行在我们自己的数据中心。数据中心拓扑旨在提供强大且可扩展的边缘网络,位于多个区域数据中心的前面,这些数据中心负责处理计算和存储工作负载。尽管我们的物理和逻辑组件中内置了冗余层,但我们的站点仍然有可能在一段时间内无法相互通信。

UTC时间10月21日22:52,为了更换发生故障的100G光纤设备,美国东海岸网络中心与美国东海岸数据中心之间的连接被断开。连接在43秒后恢复,但这次短暂的中断引发了一系列事故,导致24小时11分钟的服务降级。

\"\"

之前,我们已经介绍过如何使用MySQL存储GitHub元数据以及我们实现MySQL高可用性的方法。

GitHub拥有多个MySQL集群,大小从几百GB到5TB不等,每个集群最多有几十个只读副本来存储非Git元数据,因此我们的应用程序可以提供拉取请求和问题管理、身份验证管理、后台处理协调等原始Git对象存储之外的其他功能。应用程序不同部分的数据通过功能分片存储在各种集群中。

为了大规模提高性能,应用程序将数据直接写入每个集群的主数据库,但在绝大多数情况下将读取请求委派给副本服务器。我们使用Orchestrator来管理MySQL集群拓扑和处理自动故障转移。Orchestrator以Raft的共识算法为基础,可以实现应用程序无法支持的拓扑,因此必须十分小心让Orchestrator配置与应用程序的期望保持一致。

\"\"

事故时间表

UTC时间2018年10月21日22:52

在发生网络分区时,主数据中心的Orchestrator根据Raft共识机制启动了首领卸任(deselection)过程。美国西海岸数据中心和美国东海岸公有云的Orchestrator节点获得了法定票数,并开始对集群进行故障转移,将写入操作定向到美国西海岸数据中心。当连接恢复时,应用层立即开始将写入流量引向西海岸站点的新主节点上。

美国东海岸数据中心的数据库包含了一小段时间的写入数据,这些数据尚未被复制到美国西海岸的数据中心。由于这两个数据中心的数据库集群包含了其他数据中心不存在的数据,因此我们无法安全地将主数据库转移到美国东海岸数据中心。

UTC时间2018年10月21日22:54

我们的内部监控系统开始发出警报,告知我们的系统出现了大量故障。这个时候,已经有几位工程师正在对收到通知进行分类。UTC时间23点02分,第一响应团队的工程师已经确定很多数据库集群的拓扑处于不正常状态。Orchestrator API显示的数据库复制拓扑只包含美国西海岸数据中心的服务器。

UTC时间2018年10月21日23:07

到了这个时候,响应团队决定手动锁定我们的内部部署工具,以防止引入任何其他变更。在UTC时间23:09,响应团队将网站置为黄色状态。这样会自动将事故升级,并向事故协调员发送警报。在UTC时间23:11,事故协调员加入,两分钟后决定将网站置为红色状态。

UTC时间2018年10月21日23:13

这个问题影响了多个数据库集群。来自GitHub数据库工程团队的其他工程师也收到了通知。他们开始着手调查,看看需要采取哪些措施将美国东海岸数据库配置为每个集群的主数据库并重新构建复制拓扑。这项工作具有很大的挑战性,因为到目前为止,西海岸数据库集群已经从应用层接收了近40分钟的写入数据。另外,东海岸集群中有几秒钟的写入数据未被复制到西海岸,并阻止将新写入的数据复制回东海岸。

保护用户数据的机密和完整是GitHub的首要任务。30多分钟的美国西海岸数据中心数据写入让我们不得不考虑failing-forward,这样才能保证用户数据的安全。然而,在东海岸运行的应用程序依赖于西海岸MySQL集群的写入信息,目前无法应对由于跨国往返而带来的额外延迟。这个决定将导致很多用户无法使用我们的服务。最后我们认为,延长服务降级时间可以确保用户数据的一致性。

\"\"

UTC时间2018年10月21日23:19

通过查询数据库集群的状态,我们发现需要停掉元数据写入作业。我们暂停了Webhook和GitHub Pages,避免对已经从用户收到的数据造成损坏。换句话说,我们的策略是优先考虑数据完整性,而不是站点可用性和恢复时间。

UTC时间2018年10月22日00:05

事故响应团队的工程师开始制定解决数据不一致问题的方案,并实现MySQL故障转移。我们的计划是从还原进行备份,同步两个站点的副本,回退到稳定的服务拓扑,然后继续处理排队的作业。我们更新了状态,告诉用户我们将要执行一次内部数据存储系统的可控故障转移。

\"\"

MySQL数据备份每四个​​小时进行一次并保留多年,但备份远程存储在一个公有云的blob存储服务中。恢复数TB备份数据需要数小时时间,大部分时间用于从远程备份服务传输数据。对大型备份文件进行解压缩、校验、预处理并加载到新配置的MySQL服务器上也花费了大量时间。在整个过程中,我们每天至少进行一次测试。在这个事故之前,我们从来没有基于备份完整地重建整个集群,而是依赖其他策略,例如延迟复制。

UTC时间2018年10月22日00:41

这个时候我们已经启动了所有受影响的MySQL集群的备份过程,工程师正在监控进度。同时,多个团队的工程师正在研究如何加快传输和缩短恢复时间,并且不会进一步降低站点可用性或者损坏已有数据。

UTC时间2018年10月22日06:51

美国东海岸数据中心的几个集群已经从备份中恢复,并开始从西海岸复制新数据。这导致必须通过跨国链接执行写入操作的页面的加载时间变慢,但如果读取请求落在新恢复的副本上,那么从这些数据库集群读取的页面将返回最新结果。其他更大的数据库集群仍在恢复中。

我们的团队已经知道如何直接从西海岸进行恢复,以突破从异地存储下载导致的吞吐量限制,并对恢复过程越来越有信心,建立复制拓扑所需的时间取决于复制需要多长时间才能赶上来。这个估计是根据我们现有的复制遥测数据线性插值得出的,我们更新了状态页面,设置了两个小时作为我们估计的恢复时间。

UTC时间2018年10月22日07:46

GitHub发布了一篇博文,提供了更多的背景信息。我们在内部使用了GitHub Pages,但因为几个小时前所有的构建都已暂停,所以发布这些内容需要额外的工作量。我们对造成的延迟深表歉意。我们希望能够更快地发布这些信息,并确保在未来可以在这些限制条件下发布更新。

UTC时间2018年10月22日11:12

美国东海岸的所有主数据库都已就绪。网站的响应能力也随之提升,现在写入操作被引向了与应用程序层同处同一物理数据中心的数据库服务器上。虽然这大大提高了性能,但仍有数十个数据库读取副本比主数据库延迟了几个小时。这些延迟的副本导致用户在与我们的服务进行交互时看到不一致的数据。我们将读取负载分散到大量的只读副本中,每个请求都有可能到达已经有几个小时延迟的只读副本上。

实际上,要让复制赶上主数据库,所需的时间遵循的是功率衰减函数(power decay function)而不是线性轨迹。当欧洲和美国的用户醒来并开始工作时,数据库集群的写入负载增加,恢复过程所耗费的时间比原先估计的要长。

UTC时间2018年10月22日13:15

到目前为止,我们正在接近GitHub.com的高峰流量负载。事故响应团队就如何开展后续的工作展开了讨论。很明显,复制延迟在增加。我们已经在美国东海岸公有云中配置额外的MySQL只读副本。一旦这些实例就绪,就可以更容易在更多服务器上分摊读取请求。减少跨副本聚合可以让复制更快赶上。

UTC时间2018年10月22日16:24

在副本进入同步状态后,我们对原始拓扑进行了故障转移,解决延迟和可用性问题。为了优先保证数据完整性,我们在开始处理积压数据时保持服务状态为红色。

UTC时间2018年10月22日16:45

到了这个阶段,我们必须平衡积压数据所带来的负载,因为过多的通知可能会导致生态系统的其他系统发生过载,我们还要尽可能快地将服务恢复到100%。这个时候队列中有超过500万个Webhook事件和8万个页面构建请求。

当我们重新开始处理这些数据时,我们处理了大约200,000个Webhook负荷,这些负荷已经超过内部的TTL并被丢弃。在发现这个问题后,我们暂停了处理,并临时延长了TTL。

为避免进一步破坏状态更新的可靠性,我们一直处于降级状态,直到处理完所有积压数据并确保我们的服务已明确恢复到正常的水平。

UTC时间2018年10月22日23:03

已处理完所有待处理的Webhook和Pages构建,并确认了所有系统的完整性和正常操作。网站状态已更新为绿色。

下一步

解决数据不一致问题

在恢复过程中,我们捕获了MySQL二进制日志,其中包含我们在主站点中写入但未被复制到西海岸站点的数据。未复制到西海岸的写入数量相对较少。例如,我们最忙的一个集群在受影响期间有954个写入。我们目前正在分析这些日志,并确定哪些写入可以自行解决,哪些需要与用户进行确认。我们有多个团队参与了这项工作,并确定了有一类写入已经被用户重复操作并成功保留。我们的主要目标是保持用户数据的完整性和准确性。

沟通

我们希望在事故期间向用户传达有意义的信息,我们根据积压数据的处理速度对恢复时间进行了多次公开估算。回想起来,我们的估算并没有考虑到所有的变数。我们对此造成的混乱感到抱歉,并希望在将来能够提供更准确的信息。

技术举措

在此次分析过程中,我们确定了很多技术举措。随着我们继续在内部进行广泛的事故后分析,我们发现我们有更多的工作要做。

  1. 调整Orchestrator配置,以防止跨区域选举主数据库。Orchestrator只会按照配置的参数运行,不管应用程序层是否支持这种拓扑变更。单个区域内的首领选举通常是安全的,但突然出现的跨国延迟是导致这次事故的主要因素。这是系统的紧急行为,因为我们之前没有遇到过这么大规模的内部网络分区。
  2. 我们已经建立了一个可以更快报告状态的机制,可以更清晰地谈论事故的进展。尽管GitHub的很多部分在事故期间仍然可用,但我们只能将状态设置为绿色、黄色和红色。我们意识到,这并不能让我们准确了解哪些部分在正常运行,哪些部分出现了故障,在将来,我们还将显示平台的不同组件,这样就可以了解每项服务的状态。
  3. 在事故发生前的几周,我们启动了一项全公司范围的工程计划,通过多活设计让多个数据中心为GitHub流量提供支持。这个项目的目标是在设施层面支持N+1冗余,在不影响用户的情况下容忍单个数据中心故障。这是一项很重要的工作,需要一些时间。我们相信这种跨地理位置相连接的网站可以提供了一系列良好的权衡。这次事故加剧了这个项目紧迫性。
  4. 我们将在验证我们的假设方面采取更积极主动的立场。GitHub是一家快速发展的公司,在过去十年中已经具备了一定程度的复杂性。随着公司不断的发展,捕捉和转移权衡和决策的历史负担将变得越来越困难。

组织举措

这次事故导致我们对站点可靠性的看法发生了转变。我们已经意识到,更严格的运维控制或改进的响应时间对于像我们这样复杂的服务系统的站点可靠性来说仍然是不够的。我们还将启动一种系统性实践,在故障场景有可能对用户产生影响之前对其进行验证,我们将在故障注入和混沌工程方面进行投入。

结论

我们知道用户有多依赖GitHub给项目和企业带来成功。没有人比我们更关心服务的可用性和数据的正确性。我们将继续分析这次的事件,以便为用户提供更好的服务并赢得用户对我们的信任。

英文原文:https://blog.github.com/2018-10-30-oct21-post-incident-analysis/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281762.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php 合并 字符串_PHP如何去重合并字符串

本篇文章主要给大家介绍PHP如何去重合并字符串。推荐教程:《PHP教程》对于PHP学习者来说,合并多个字符串,应该并不是很难。但是如果这多个字符串中,有相同元素,当我们想要合并他们并且要使其值具有唯一值。也就是说合并…

软概(lesson 2):课堂测试

一、测试题目 二、完成过程 1.设计思想 ①连接mysql数据库 ②设计user类,增加参数 ③设计add类,向数据库内增加内容 ④设计addInput页面,完成录入操作 ⑤设计add页面,接收录入的参数,并调用add类函数 2.源代码 user.ja…

谷歌Gboard输入法新增“无痕模式”:仅在Chrome隐身窗口中适用

据外媒Android Police报道,如大家所知道的,Chrome浏览器中的“隐身模式”是为了防止你的私密浏览记录被其他人看到,但是,在这种模式下,你的输入法键盘依然会记住你输入的短语,为了阻止你的键盘在Chrome隐身…

php两个数组融合,php合并两个数组的方式有哪些

1、arrary_merge示例代码:$arr1 array(1, 2, 3, 4, 5);$arr2 array(1, 2, 6, 7, 8, 9, 10);$result1 array_merge($arr1, $arr2);$arr3 array("name" > "itbsl", "age" > 13, "sex" > "Male");$arr…

最近对latin-1这个字符集产生了不少好感

【简介】 最近我要解析一个数据库中间件的日志、这个中间件会在日志中记录SQL发往的后台DB ,执行耗时,对应的SQL;中间件直接把SQL写到 了日志中去,并没有对SQL进行适当的编码转换;理想情况下这个也不会有什么问题,不幸…

面象对象设计原则之六:迪米特原则(LeastKnowledge Principle, LKP)

迪米特法则来自于1987年美国东北大学(Northeastern University)一个名为“Demeter”的研究项目。迪米特法则又称为最少知识原则(LeastKnowledge Principle, LKP),其定义如下: 迪米特法则(Law of Demeter, LoD):一个软件实体应当尽可能少地与…

其他对象的表单

1.textarea&#xff1a; textarea对象就想是input对象中的text样式的表单&#xff0c;只不过是扩展过的text样式表单。它可以通过行&#xff08;rows&#xff09;属性和列&#xff08;cols&#xff09;属性来编辑文本域的大小。最常见于留言板、论坛时回帖时的文本框等。 <h…

WinForm(十三)WebView2

WebView是WinForm框架中一个控件&#xff0c;用来对网页信息交互&#xff0c;有时Web自己开发的&#xff0c;有时Web是三方的。下面通过一个例子来看看WebView2的使用。首先看Web的逻辑&#xff0c;是一个商品添加页面&#xff0c;用AlpineJS和BootStrap来开发的&#xff0c;业…

Fluent UDF【4】:C语言

Fluent UDF利用的是C语言&#xff0c;本文简单介绍在UDF中经常会用到的C语言常识。 本文部分内容来自UDF手册。 1 C语言中的注释 C语言中的注释利用/*及*/来实现。例如: /*这是一个注释*/ 注释也可以跨行实现&#xff0c;如: /*这是一个 跨行注释*/ 注意:在编写UDF的过程中&…

java 画砖块,钢笔画入门:教你画砖块

说到砖块很多朋友会想到搬砖&#xff0c;绘画吧今天要教大家用钢笔画一块砖&#xff0c;因为画建筑的时候经常要画砖墙&#xff0c;我们先从简单的砖块学起&#xff0c;之后绘画吧会给大家分享画一面砖墙的哦。绘制要点&#xff1a;本教程的主体物选择了一块有小残缺面的砖头。…

[转] Node.js的线程和进程

[From] http://www.admin10000.com/document/4196.html 前言 很多Node.js初学者都会有这样的疑惑&#xff0c;Node.js到底是单线程的还是多线程的&#xff1f;通过本章的学习&#xff0c;能够让读者较为清晰的理解Node.js对于单/多线程的关系和支持情况。同时本章还将列举一些让…

第三方支付异步通知的陷阱

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/j16421881/article/details/78703792 用户下单后调用第三方支付付款&#xff0c;然后接收第三方支付的异步通知&#xff0c;以便确认支付是否成功。 如下图 但异步通知可能…

2.3 万 Star,Nginx 可视化配置工具

你好&#xff0c;这里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;实用的工具或组件&#xff0c;希望对您有用&#xff01;对于前后端开发工程师来说&#xff0c; Nginx 是必须掌握的工具&#xff0c;因为它不仅仅是一个 Web Server&#xff0c;还包含了其他…

城市智慧停车系统方案的产品设计体系介绍

最近几年随着大数据技术快速发展与应用&#xff0c;智慧城市随即被正式提出。而且&#xff0c;我们也可以深刻感受到“智慧”正在慢慢改变我们的生活方式和城市。要让城市变智慧的地方太多太多&#xff0c;当前我们接触做多的可能就是外出停车&#xff0c;比如很多商场的停车系…

vue.js:利用vue.js做一个抽奖小游戏

MVVM模式是什么&#xff1a;MModel(模型)&#xff0c;VView&#xff08;视图&#xff09;,VM ViewModel(简写成MVVM) . 代码如下&#xff1a; 运行代码结果&#xff1a; 1.你没有中奖&#xff1a; 2.恭喜你&#xff0c;你中奖了&#xff1a; 转载于:https://www.cnblogs.com/ya…

滚动加载数据 php,无刷新动态加载数据 滚动条加载适合评论等页面

滚屏加载更多数据,适合评论等页面本例的数据库很简单&#xff0c;一看就明了复制代码 代码如下:$querymysql_query("select * from content order by id desc limit 0,10");while ($rowmysql_fetch_array($query)) {?>js文件复制代码 代码如下:$(function(){var …

国际主流固件接口组织UEFI全面支持LoongArch,龙架构已完成上游TianoCore EDK2代码合并...

2022年9月初&#xff0c;UEFI官方组织在发布的UEFI specification V2.10规范中全面支持了LoongArch64架构以及部分LoongArch32架构。近期&#xff0c;龙芯团队又完成了LoongArch基础代码与UEFI上游TianoCore EDK2的合并&#xff0c;LoongArch进入TianoCore EDK2主分支&#xff…

Invalidate和postInvalidate

为什么80%的码农都做不了架构师&#xff1f;>>> Android提供了Invalidate方法实现界面刷新&#xff0c;但是Invalidate不能直接在线程中调用&#xff0c;因为他是违背了单线程模型&#xff1a;android UI操作并不是线程安全的&#xff0c;并且这些操作必须在UI线程…

.Net轻松处理亿级数据--clickhouse及可视化界面安装介绍

前言我是在17年就听说过Clickhouse,那时还未接触过亿数据的运算&#xff0c;那时我在的小公司对于千万数据的解决方案还停留在分库分表&#xff0c;最好的也是使用mycat做的集群。这些解决方案都比较复杂&#xff0c;毕竟通常来说那些需要大量存储的数据基本都是像日志&#xf…

NET CORE读取Excel.xlsx单元格内的图片,并关联当前业务ID推送图片到指定服务器...

NET CORE读取Excel.xlsx单元格图片的场景&#xff0c;一般是批量导入业务数据&#xff0c;例如&#xff1a;药品的图片&#xff0c;医师资格证&#xff0c;商品上架、商家营业资质、水果信息、用户头像等等这里我截个图&#xff0c;图文并茂更好理解特别声明&#xff1a;粘贴图…