`
edge
  • 浏览: 66530 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

互联网巨头为什么会“宕机” ——超大规模分布式系统总体失效原因探析

阅读更多

 

       说明:本文是作者以往跟踪部分大型互联网服务提供商(GoogleAmazonFacebookMS等)出现的俗称大规模宕机(本文所称总体失效)案例进行的原因分析,结合分布式系统设计方面的一些经验所做的粗浅总结。因google最新一次宕机而参与微博话题的相关讨论,将以前的一些思路和最新的学习整理出来,算是这个领域的一个普及贴吧,供批判之用。

 

一、大型分布式系统为什么会失效

       首先,明确一下我所谓“总体失效”的含义,也就是俗称的“XXX宕机事件”。如同此次(2013年8月16日)google出现的情况——据新闻报道:“美国西部时间下午3点50分到3点55分,约5分钟时间内,Google大部分服务无法访问,从出现宕机到完全恢复总时间为11分钟”。无论从故障现象(无法访问)、时间跨度(5-11分钟)以及影响范围(某些媒体称大约50%-70%的访问返回异常,其他媒体描述为无法访问,没有提及范围)几个角度看,都不属于系统设计目标应该出现的失效水平,因此可称总体失效,也就是常说的服务不可用。

 

       问题随之而来:所谓云计算也好、大规模分布式系统也罢,最起码的一个特性就是不能因为局部故障(应用崩溃、硬件故障、网络中断)而导致整个系统中断服务——高可靠/可用性是此类系统的天然标签。更何况在当今这个集群技术如此平民化,防止单点故障(SPOF)的概念深入人心的时代,就算是规模远不及google这个数量级的系统,一般情况也不会轻易出现系统整体中断运行。因此,要分析这种现象的根本原因,必须先排除一些其他情况:

 

  1. 少量节点出现故障,故障节点简单失效——这个刚刚说完,最基本的高可用性设计也能控制住这种情况,不足为虑。但要注意“简单”二字,这是引出后续话题的关键。

  2. 大量节点在瞬间同时出现故障——既然少量节点故障不足以产生严重后果,那么大量节点同时故障呢?且不说这种概率比各种超级彩票中头奖大还是小,就算是一个数据中心突然停电这种故障,对于google这类全球分布的系统,也是充分可以应对的:后果只是区域性服务中断,虽说影响范围已经够大了,但和本文开头描述的情况还有很大区别。如果你再追问:如果真的是很巧合,全球范围内所有数据中心同时故障呢?那咱们还是谈谈买彩票的事情吧,更何况迄今为止的案例不支持这种猜测。

  3. 流量过大等外部因素。这一点对于小型网站而言可能成为突发问题,即使如此,一般的可靠性设计也能保证过多请求被拒绝,而大部分服务仍可访问,只是时断时续或者速度变慢。更何况对于google这类互联网巨头,流量基本上不成为问题,至少迄今为止的事故没有因此引起的,即使是小规模故障+流量突增,估计也不是问题。(当然要注意一点,不是说外部因素都不会引发问题,后面会有一个实际案例说明外部因素如何导致无法访问的问题。)


       这三种情况排除了,那还有什么可能性呢?这就是逻辑的力量发挥作用的时候了,通过简单推理就可以得出结论:要形成大规模故障或总体失效,只有一个模式,那就是系统一开始出现了局部的、小规模的故障,然而由于种种原因,故障影响的范围越来越大,最终导致了全局性的后果。这结论听起来很简单,好像也颇有些道理,但就是感觉太抽象,对于发现和解决问题没啥实际意义。因此,继续论述这个观点之前,先来讲两个案例:

 

       第一个案例是笔者在实际工作中遇到过的情况,相信很多人都知道这类场景。应用服务器集群是去中心化的设计,采用基于会话复制的故障转移模式,每个节点根据某种算法找到其对应的复制节点,系统出现故障时,所有对故障节点的访问根据其session复制的信息转移到复制节点上。这种模式的一个主要问题是随着系统持续运行,会话复制的算法如果不能够在各个节点间分配很均衡,会导致某个节点(B)接收大量来自于单个主节点(A)的复制会话。当这个主节点(A)发生故障切换时,该复制节点(B)瞬时压力过大,再次出现崩溃。而一旦该节点(B)全部会话的复制又不均衡,继续压垮其对应的复制节点(C),就可能形成连锁反应,导致多个节点甚至整个集群故障。最终评估下来,采用这种故障转移模式的本意是提升用户体验,希望做到不因单个节点失效而要求部分用户重新登录,可惜只是“看上去很美”,搞不好就出现灾难后果。如果没有更好的解决方案,还是简单失效比较好,也就是放弃会话复制+故障转移的模式,一个节点故障,就让其上所有用户重新访问,带来的是整个集群的稳定与可靠。

 

       这个案例当中,众多关键因素都已经现身了:

  1. 节点间存在状态的复制,并且是系统本身可靠性设计的一部分

  2. 一个节点故障时对于其他节点会产生影响(注意这和第1点不完全是一回事,两者可以相互独立存在,比如复制的不是session而是其他数据)

  3. 相关复制算法设计也有不太完善、值得商榷的地方

  4. 对故障转移策略的选择才是最终造成/解决问题的关键

       唯一有点缺乏说服力的地方在于这是一种普通应用的场景,与互联网上堪称大规模分布式系统的形态相去甚远,我们完全有理由相信互联网巨头们的设计根本不会有这方面问题。其实在这个案例中,更好的复制算法、更大量的机器以及更轻的session使用方式等,都能解决问题,从而继续保持故障转移的特性。所以,这个例子只是为了引出相关概念,还要找一个更有代表性、更有说服力的案例才能进一步深入分析。

 

       第二个案例是亚马逊2011年4月21日宕机事件。根据亚马逊官方故障分析(参见[1]),运维人员在对一个集群进行升级/维护时出现了误操作,一部分机器切换到了错误的网络,导致实际处于断网的状态。维护人员发现这一错误并恢复了网络连接,但这却是灾难的开始:这个集群中,所有那些作为数据存储主节点的机器(其实每台机器都应该是某部分数据的主存储节点,所以实际上就是所有机器),在断网期间,由于找不到其对应的数据复制节点,自然认为是复制节点出现了故障(这一点很关键)。在恢复网络连接后,立刻开始寻找可以复制的节点,并进行数据复制操作。可想而知,大规模数据同时开始复制,对于节点的I/O以及网络流量都产生巨大压力,造成所有受影响的服务器响应缓慢。光这样还不算,根据亚马逊的说法,这种混乱的情况还进一步触发了极为少见的资源争用的情况(race condition,这不是很显然嘛,资源都这样了还不争用?我的理解说白了就是隐藏很深的bug,没有这种极端的临界条件不会触发),使得整个状况更加糟糕,最终导致很多节点已经找不到对应的复制节点,只好对一切访问都stuck在那里(找到复制节点之前,允许用户操作将造成数据丢失的可能性)。好在亚马逊的EC2/RDS等大规模服务本身就是按照可用性分区(Availability Zone)管理的,各个区之间网络和数据都是相对隔离的,很多区构成一个区域(Region),而亚马逊在全球一共有若干个区域。这样设计的目的显然能起到故障隔离的效果,按理说一个zone之内的系统出上面所说的问题,也就传播到这个zone内部为止。然而,亚马逊EC2、RDS拥有一个统一的管理系统(从文字的表述看,应该是全球统一的),当一个zone出现问题之后,通过管理系统对这个zone当中的节点进行操作变得超级慢,而由于虚拟机的操作(尤其是创建磁盘卷等)本身就是耗时操作,因此API超时时间设置都很长,无法通过超时而释放线程,最终耗尽了管理系统的线程资源。好在管理系统的API线程池是按区域(region)分开设置的,才使得最终只有整个美东区域受影响,否则在用户操作层面看就是全球大宕机了(作为虚拟机、数据存储等功能本身还是不会受到影响的)。

 

       这个案例中,局部故障因为某些因素而快速影响到更大的范围这一模式也明确存在,不过故障的产生和传播相对于案例一所提出的四个主要因素之外,又新增了其他原因,比如人工运维误操作、大规模数据复制导致的系统性能下降等。总之,确实如“How Complex Systems Fail”当中提出,前面也一再说明的:普通的单点故障一般都已经被有效的设计所隔离,大型系统总体失效一定是多种因素共同作用的结果。

 

(未完待续)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics