关于分布式系统:分布式系统中亚稳定失败状态

3次阅读

共计 3121 个字符,预计需要花费 8 分钟才能阅读完成。

这篇文章的初衷,是记录拜读由 Nathan Bronson, Aleksey Charapko, Abutalib Aghayev, and Timothy Zhu 独特发表的论文 Metastable Failures in Distributed Systems 的播种,这篇论文形容了一个在大规模分布式系统中很常见的失败场景:亚稳固失败(metastable failures),它们为什么通常在高负载分布式系统中产生,以及解决问题的思路框架:如何辨认和从亚稳固失败中复原,甚至如何防止产生亚稳固失败。

事实世界中的亚稳固失败

下图是某个公园中十分驰名的徒步路线中十分要害的一部分:两座山之间一段狭长的山脊,在两座山之间徒步,只有扶着铁链穿过这段山梁能力保障平安。能够假想这段铁链就是一个分布式系统。

当公园不对徒步者人数做限度时,就有可能引起人群拥挤以至于长时间在终点期待去尝试减低负载。你能够设想一下”零碎“经验了以下的状态转换。

  1. 稳固状态(Stable state)
    当人群低于某个平安阈值时,任何一个危险因素(例如:迟缓通过铁链的徒步者)都可能引起降速,然而零碎依然可能自愈。
  2. 软弱状态(Vulnerable state)
    拥挤人群的数量继续减少超过了某个阈值,对于每段铁链的竞争也会减少 —— 下山的人必须要期待上山的人通过,或者罗唆冒险不应用铁链而绕过他们。同样,上山的人也必须期待下山的人通过。当这种模式产生时,只有拥挤人群的数量低于某个阈值,零碎依然是能够工作的,但它当初是十分软弱的,可能变成不可自愈的失败状态。
  3. 亚稳固失败状态(Metastable Failure State)
    当零碎处于软弱状态,某些危险因素可能导致状况好转。设想一下,一组徒步者须要破费更长的工夫通过铁链,这将会使其余上山和下山的人速度降下来。越来越多的人期待,导致在铁链两端和身在其中的残余空间越来越狭隘,进而导致人们须要更多的工夫通过,进一步导致更多的人期待 … 状况循环好转 —— 进入亚稳固失败状态。

    放弃零碎处于亚稳固失败状态的正反馈循环

因为这个自续的反馈循环,零碎将放弃在这个状态,即便移除最后的诱发危险因素。为了复原,须要采取其余的措施,例如将负载升高到特定阈值以下。

亚稳固失败定义

对于亚稳固失败的定义论文中形容如下

亚稳固失败产生在对于负载起源没有管制的开放系统中,一个危险因素导致系统进入一个蹩脚的状态,并且会继续存在甚至危险因素被移除。在这个状态零碎的效率通常会很低,并且会产生继续影响——通常使工作负载放大或者整体效率升高——阻止零碎从这个蹩脚的状态中复原。
Metastable failures occur in open systems with an uncontrolled source of load where a trigger causes the system to enter a bad state that persists even when the trigger is removed. In this state the goodput (i.e., throughput of useful work) is unusably low, and there is a sustaining effect — often involving work amplification or decreased overall efficiency — that prevents the system from leaving the bad state.


如果这样,那么为什么不总是运行在稳固状态?诚如,在许多零碎中高效的资源利用是十分重要的,所以许多零碎抉择运行在软弱状态而不是稳固状态,已取得更高的效率。
当零碎处于亚稳固失败状态,零碎不会自愈,想要复原须要采取重要措施,例如升高负载。

问题的症结:正反馈循环

正反馈循环是亚稳固失败产生的本源。例如,在维基百科中给出了这样例子:

A生产了更多的 BB 反过来又生产了更多的A

又例如,人群狂奔:假如美国纽约街道上正在进行独立日游行,忽然有人开始奔跑(A)导致四周人群开始恐慌(B),更多的人开始奔跑(A)更多的人开始恐慌(B)更多人开始奔跑。。。最终导致人群狂奔(兴许当初还没有枪响)。

可能有很多不同危险因素可能将零碎带到亚稳固失败状态。然而,可能将零碎放弃在这种状态甚至在移除该危险因素之后依然不能发生变化的,是自我维持的反馈循环。

亚稳固失败的例子

  1. 重试导致工作负载放大
    假如咱们有一个 web 服务端承接客户端申请,长久层数据库服务的性能为 300 QPS 和 100 毫秒的提早,服务端有一个原生的重试机制:每次申请失败都会立刻重试。

只有服务端入流量的申请负载低于 150QPS,即便产生重试,当一个危险因素(例如短暂的网络故障)产生并导致申请积压它仍然能够自愈。这就是“衰弱”状态。

然而,当负载超过 150QPS,零碎将进入“软弱”状态——假如负载为 280QPS,当处于这种状态时零碎仍然还是能够工作的。当初,如果在服务端和数据库间接有 10S 的网络断开,数据库将面对流量的陡增(原始流量 + 重试),这将减少申请提早进而导致更多的重试,进一步减少申请延。导致一个自续的循环。

  1. 为 happy path 所做的优化工作
    任何为 happy path 优化而做出的致力都更可能进入亚稳固失败状态。假如上边同样的零碎然而有一个缓冲服务以升高数据库服务的调用次数。如果缓存命中率是 90%,那么服务端在软弱状态下可能解决 3000QPS(服务端只有 300QPS)的负载。然而如果缓存服务因为某些起因须要重启,那么咱们将面临一个问题:它将是完满进入到亚稳固失败状态的诱因。论文中将 3000QPS 称为外表容量(advertised capacity)(零碎将处于软弱状态的下限),而 300QPS 是隐含容量(hidden capacity)(零碎可能自愈的下限)。

以上展现的工作负载放大在许多大规模申请中断时是十分广泛的。然而钻研的案例我发现最有感兴趣的是“连贯不均衡”,因为应用 MRU 策略,两个零碎之间的连贯中最慢的连贯总是被抉择。

如何解决已知的亚稳固失败

在论文中形容了一些预防已知亚稳固失败的技术:

  1. 专一于危险因素的继续反馈循环
    去定位一个亚稳固失败模式,专一于弱化正反馈循环,这波及到工作负载放大,而不是针对危险因素打地鼠。
  2. 辨认最强反馈循环
    了解哪里是产生工作负载放大最大的实例,而后为它定义一个最大值。大体上,辨认最强反馈循环并且不要追赶每一个反馈循环。
    如何辨认他们呢?压力测试是一个形式。然而挑战是越大规模的服务,反馈循环越强,所以第一次在大规模服务中会发现很多问题。
    因而,你能做的事件是辨认被危险因素影响的特色指标:例如,上述实例中的重试率。通过这样,你能够了解稳固、软弱和亚稳固失败状态的边界。
  3. 弱化反馈循环
    论文形容了一些弱化反馈循环的办法。例如包含减弱负载和熔断机制。次要的挑战是这将由客户端来决策何时重试和故障转移,然而客户端通常没有全局信息(并且试图去提供这种服务自身也可能导致失败)。辨别短暂的负载峰值和持续性的过载是十分重要的,你可能须要有指标帮忙你去精确的辨认这两者。

论文为组织激励提供了一个很好的示例,处分正确的优化措施(例如优先升高资源使用率)而不是在更有可能导致亚稳固失败的 happy path 上的优化。

总结

心愿通过以上的探讨能有所收益,心愿下次在发现”一些列的申请失败“、”死亡螺旋“、”彻底失败“等等,你能够应用这些作为一个思考框架或者通用语言去了解他。论文中还有许多其余的示例和思考,感兴趣能够浏览一下论文原文。

原文地址:Metastable Failures in Distributed Systems: What Causes Them and 3 Things You can do to Tame Them

正文完
 0