当前位置: 首页 > 科技观察

来自谷歌的高可用架构概念与实践

时间:2023-03-18 16:49:01 科技观察

在谷歌,我参与了两个比较大的项目。首先是YouTube,包括视频转码、流媒体等。谷歌的存储量很大,每个月的存储量为1PB。存储和转码之后,我们还做GlobalCDN。到2012年,峰值流量达到10TBps,全球有10万个节点。几乎每台机器都是16/24核全开,10G上行也全开。然后我加入了谷歌云平台团队,也就是Borg团队。这个团队的主要工作是管理谷歌在全球的所有服务器,全球大约有100万台服务器。另一个是维护Borg系统。同时,我也是Omega系统运维的主要负责人。遗憾的是,由于种种原因,这个项目在内部被取消了。下面我想和大家分享的是关于可用性和可靠性的一些想法和思考。1、决定可用性的两个因素可用性不用谈,只谈SLA。大家可以看下图:要谈可用性,首先要承认,当一切都不可用时,只是不可用的程度。一般来说,在我们的概念里,一个服务至少要达到99.9%才叫基本可用,一个合格的产品。否则,基本上很难被别人利用。从3个9到4个9,并将不可用时间从8小时缩短到52.6分钟,这是一个很大的改进。Google中只有9个以上的4个服务会配备SRE。SRE必须在接到报警后5分钟内上线处理问题,否则报警系统会自动升级到下一个SRE。如果没有,直接报警给你的老板。您可能听说过Google搜索服务的可用性在全球范围内是5到6个九。其实这是一个多层次、多层次、全局的概念,具体到每个节点上其实没有那么高。比如北京王府井楼上的搜索集群节点,就是按照三个九设计的。关于SLA的另一个秘密是,一般大家都在谈论年度SLA,但是年度SLA除了客户补偿外,一般没有实际的工程指导意义。Google更看重的是每季度的SLA,甚至是每月的SLA,甚至是每周的SLA。这带来了更大的挑战。看这张图为什么有用,因为99%,99.9%基本可以靠运气。堆人最多可以做到3个9,也就是3班倒这样的强制性班次基本都做到了。不过,从3个9开始,基本上已经超出了人力所能及的范围。考验的是业务的自愈能力、架构的容灾能力、容错设计、容灾系统的完善程度等等。说了这么多,作为架构师,我们如何系统地分解“提高SLA”这个问题。这里我介绍两个工业级的概念MTBF和MTTR。MTBF:平均无故障时间。通俗地说,就是一个东西有多不可靠,坏的频率有多高。MTTR:平均恢复时间。这意味着服务中断后需要多长时间才能恢复。有了这两个概念,我们可以提出一个服务的可用性取决于MTBF和MTTR这两个因素。从这个公式出发,结合实际情况,很容易弄清楚高可用架构的基本数量。即:要么增加MTBF,要么减少MTTR。没有别的办法。需要注意的是,无论是MTBF还是MTTR都不能脱离实际。从理论上讲,作为一个正常人,接到紧急警报、正确分析问题、找到正确解决方案、【正确实施】的时限约为【两分钟】。我个人认为这个标准是高不可攀的。作为一个努力多年的Oncall工程师,2分钟就能看清告警,上VPN,找到dashboard,还不错。就算是已知问题,有解决办法,能正确输入命令,也至少需要15-20分钟才能完全成功。所以如果按照这个标准,管理服务要做到4个9,那么一年只能坏一次,两次就超标了。实现高可用基本靠运气~回过头来说说MTBF。请思考影响服务MTBF的三大因素!发布发布或发布!这个术语称为年龄死亡率风险。一般只要不碰,一个服务一年不会坏一次。更新越频繁,越容易坏。所有的软件都有漏洞,修复漏洞的更新也会引入新的漏洞。新版本、新功能是MTBF最大的敌人。2、高可用解决方案中提到了MTBF和MTTR这两个定义,那么应该如何付诸实践来提高可用性呢?先说几个大家可能听腻了的解决方案。1.提高冗余度,运行多个实例,以资源换取可用性。道理虽然很简单,但实施起来却并不容易。有很多很多细节需要考虑。第一个细节:N+2应该是标准的。N+2的意思是如果一个服务需要1个实例才能正常提供服务,那么我们在生产环境中应该部署1+2=3个节点。你可能觉得N+1比较合理,就是有热备份系统,这样比较容易接受。但是你要想一想:服务N+1部署只能提供双机热备容灾,一发布就失去了保护。因为刚才也说了,发布不成功的几率非常大!从另一个角度来看,服务N+2意味着在最大的两个实例丢失的情况下,仍然可以维持业务的正常运行。这其实有点像最近常说的两地三中心的概念。第二个细节:实例必须是平等和独立的。不要一大一小,互相依赖。否则你的N+2就不是真正的N+2。如果两地迁移三个中心之一需要24小时,那么就不是高可用部署,应该叫异地容灾系统。第三个细节:流量控制能力很重要。要实现高可用性,你必须有一个非常可靠的流量控制系统。这个系统按照通用的维度调度是不够的,比如源IP和目标IP。最好根据业务维度来调度流量。比如按API调度,甚至按用户类型、用户来源等调度,为什么?因为一个高可用的系统必须支持以下场景:隔离。用户A发送的请求和用户B发送的请求在同时处理时可能会发生冲突,需要隔离。隔离。用户A发送的请求可能会消耗过多的资源,这种请求必须钉在有限数量的节点上,才能顾全大局。死亡查询。每个人都遇到过。用户上线后发送异常请求直接挂断服务。如果连续发送几个,整个集群就会宕机。如何实现高可用性?那么,针对这种类型的防御就是在几台服务器挂掉之后,自动屏蔽类似的请求。需要结合业务来分析。但是如果要实现高可用,这些都是必须的,也是肯定会遇到的场景。还是那句话,靠人是没有用的。2.变更管理(ChangeManagement)还记得影响MTBF的最大因素吗?如果发布质量不提高,一切都是空谈。第一点:离线测试(OfflineTest)离线测试总是比在线调试容易100倍,安全100倍。道理很简单,就看实现了。如果你的团队没有完整的线下测试环境,那我的意见是不要接新业务,先花点时间把这个搞定。这包括代码测试、数据兼容性测试、压力测试等。台上一分钟,台下十年功。可用性的阶段性提升,靠的不是运维团队,而是产品团队。可以离线完成的测试不应该在线测试。第二点:灰度发布的原理看似很普通,但是在实现上却很有讲究。首先,灰度发布是速度和安全之间的折衷。他是最后一个出台许多政策的人,而不是唯一一个。如果灰度只是为了灰度,故意拖慢进度,会导致多个在线版本长期并存,可能会引入新的问题。如果你做灰度发布,如果是匀速的,说明你还没有理解灰度发布的意义。一般来说,阶段选择从1%->10%->100%呈指数增长。现阶段根据不同的具体业务按维度进行细分。这里的重点是,1%并不是全部随机抽取,而是根据业务特征和数据特征,抽取一组代表性很强的例子,作为灰度发布的豚鼠。甚至每个版本的第一阶段用户(我们称之为金丝雀/金丝雀)也是根据每个版本的特点人为选择的。如果你要发布一个只对亚洲用户开放的功能,那么使用美国或欧洲集群进行发布实验显然没有意义。从这个角度来看,灰度发布能做的事情是不是很多?真的不是机器分割那么简单。回归本质:灰度发布是上线最后的安全保护机制。即不能太慢,让产品团队过度依赖,也不能太随意,失去意义。总之,灰度发布全在细节。第三点:服务必须提供回滚支持,不允许讨论!这么重要的话题,我想用感叹号来强调一下!不过估计在现实中,大家也听过各种各样的理由。这里我有三个买不到的秘籍,今天就分享给大家,保证药到病除。原因一:我的数据修改后,格式和之前的不兼容,无法正常回滚!秘籍一:设计开发时考虑兼容性问题!!!例如,不要更改数据库中的字段,只需添加另一个字段即可。数据存储格式最好使用protobuf,一种支持数据版本,支持前后兼容的方案。在最坏的情况下,有必要在实施变更“之前”考虑清楚数据兼容性问题。没有回滚脚本,没有更新,至少要做好战斗的准备。原因2:我的更改删除了一些东西!回滚后数据没了!秘籍2:你一定是在开玩笑吧。键入此更改并将其分成两半。前半部分禁止访问此数据。发布后确实没有问题,然后下半年发布,下半年删除数据。这样,执行完前半部分,就需要回滚回去了。原因三:我的改动发布后,其他依赖这个系统的人会得到错误的数据,回滚也没有用,他们不再接受旧数据!秘籍三:这个在配置管理、缓存等系统中比较常见。对于这类问题,最重要的是制定与版本无关的刷新机制。触发刷新的机制应该独立于发布过程。必须有一种方法来强制刷新数据。以上三个秘籍涵盖了100%的回滚兼容性问题,有的话请告诉我!回滚兼容性问题是一个整体问题。只有开发和运维双方都意识到这个问题的严重性,才能整体解决这个问题。而如果回滚问题不能解决,就不可能实现高可用。3.可用性7级图说完变更管理,再给大家带来一个7级图,看看你的服务处于哪个级别的可用性。当服务挂起时...级别1:因数据损坏、破坏而崩溃。这对于内存数据库来说很容易。出乎意料的事情发生了,所有数据都丢失了。写硬盘写到一半,死机后,不仅进程中的数据没有了,旧的数据也全部丢失了。当涉及到这样的系统时,我对你只有同情。第二级:Crashwithnewdataloss。一般来说,正常的服务应该这样做......挂断后最多也就丢失几秒的数据。第三级:无数据丢失的崩溃。要达到这个水平,需要一定的技术投入。至少想清楚怎么绕过OS的各种缓存,怎么绕过硬件的各种坑。第四级:没有崩溃,但没有或非常有限的服务,服务质量低。一个更好的系统应该不会在任何时候崩溃……如果一个程序能够正常处理异常输入、异常数据等,那么就给高级流控系统创造了条件。它可以导入其他用户流量并将问题流量发送到一侧,而不会造成太多容量损失。5级:部分或有限的服务,具有良好至中等的服务质量。这个水平不错如果多个服务在同一个实例上运行,至少不是所有服务都被破坏了。有些服务总比没有服务好。级别6:具有显着用户可见延迟的故障转移,接近完整的服务质量。只有到了这个层次,你才能摸到高可用的大门,也就是有容灾措施。但是可能自动化程度不高,或者一些关键问题没有解决,业务可以恢复,但是比较慢。第7级:故障转移,用户可见延迟最小甚至没有,接近完全服务质量。这边蝴蝶扇动翅膀,天空中掀起雷雨,将整个机房摧毁。结果,生意完全没有受到影响。蓝翔技校一铲下去,整个网络都为之颤抖。哎,高可用就是为这种东西准备的。问答1。有评价体系吗?评估系统的第一步是收集足够的信息。要想知道自己的服务是否高可用,首先要监控!不仅是黑盒监控,还有白盒监控。如果有一个自动化的SLA监控系统,可以实时显示SLA的变化,对系统的开发计划会有很强的指导作用。2.能否详细说明一下要做到“死机不丢”需要在哪些方面下功夫?这说起来简单,但在实践中实施起来非常复杂。因为很多东西都有无数的坑。例如:如何绕过操作系统的缓存。系统硬件也可能有内置Cache,Firmware也可能有BUG等。一些集群系统为了所谓的性能也实现了假同步。这里的列表是不完整的。我说的这个层次就是让大家有这个意识去系统的处理这个问题。比如是否需要存储更多的关键数据,然后做一些销毁测试。比如模拟停电等极端情况,让我们有备无患。扫地雷比打地雷容易多了。3、Coding.net现在打了多少个9,7个图是什么水平,改造用了多长时间,有什么坑分享一下?首先,高可用是基于业务的。不是所有的业务都能实现高可用,也不是所有的业务都需要实现高可用。我们在关键业务上投入了大量精力,比如Git系统的流控、数据安全等,除此之外我们无能为力。4、开发团队应该如何配合?如何匹配周期?重点在哪里(开发更偏向于业务)?首先是确定一个共同的目标。高可用性是有代价的。你的业务需要达到什么程度,必须是一个系统的考虑。举个例子,Youtube上有那么多视频,但是每个视频的每种格式只保存一份。所以可用性肯定会受到影响。不过数据量太大了,各种小猫视频真的不重要。相比之下,广告视频通常存储8个副本。所以!如果你想提高可用性,你必须找到与开发团队的共同目标。这里再给大家一个秘籍,那就是errorbudget。与开发团队一起确定可用性,比如99%。如果业务团队做出来的东西不好,在各种情况下,最终达不到这个标准。很抱歉,暂时不要发布新功能,只修复错误。5.Google的SRE工程师用什么开源工具来管理数百万台机器?很惭愧,我们没有使用任何开源工具,都是内部开发的。Puppet用于企业内部管理,不用于生产系统。6、请问独立的点对点N+2服务用什么架构比较好?LVS+Keepalive热备合适吗?我们现在不都用haproxy/nginx之类的7层代理吗?但其实原理是差不多的。只要达到你的目的,就可以动态切换。7、“可以导入其他用户流量,把有问题的流量送到一侧,不会造成太大的容量损失。”你怎么理解这句话?另外,如何区分问题流量?这句话指的就是刚才说的高可用必不可少的流控系统。没有一个系统是完美的,总会有各种热点和薄弱环节。问题流量的定义与业务密切相关。再举个例子:当年Youtube的CDN服务器有问题。后端存储变慢后,前端的请求就会聚集在一起,像水管一样,内存爆了。如果压力突然太大,它肯定会死。如何处理这个问题?最后升级流控系统,每个实例上报自己的内存状态,超过限制后流控系统自动绕过。通过将这个问题变成一个自动化的解决方案,问题区域就大大减少了。又如,搜索系统是一个典型的热点密集型系统。一些生僻字,查一次,到各种硬盘。热词消耗很少。因此,流控系统有一个功能,每个请求回复都有一个成本值,流控系统自动平衡整个集群。8、关于回滚,如果我想增加一个删除功能,如何将这个操作分成两半,用户进行了删除操作,但是禁止删除数据,会不会出现数据不一致的情况?这是刚才说的秘籍的第二篇。其实金手指的第二条规则就是拆!没有解不开的释放。将其移开,直到它可以安全地向前滚动然后再向后滚动。9、能否简单介绍一下100W台服务器是如何实现自动化管理,及时发现故障,自动修复,并报警的?问题其实没有那么复杂。就是在每台机器上运行一个agent,这个agent进行定期的巡检操作,有问题会通知管理系统自动下线。平时注意收集问题即可。比如线上突然出现了不同时间的问题,那么就把它加到agent中,下次就会自动检测并修复这个问题。10.有没有什么好的办法处理querytodeath?这个问题比较难。一般需要做一层更智能的业务代理。当业务代理检测到请求发送到哪里,哪个后端挂了,就可以进行一些处理。另一种方式是在挂起之前在后端记录日志,在处理之前先记录下来。我正要处理这个请求,一半就挂了。重启后查看日志,发现上次处理请求是挂起的,那么就可以阻塞请求了。