分布式高可用:故障恢复

分布式高可用:故障恢复

  • 前言
  • 故障类型
  • 故障检测
  • 故障恢复
  • 分布式故障检测原理
  • 故障恢复策略
  • 知识扩展:固定心跳检测和基于历史心跳信息预测故障的策略,各有什么特点呢?
  • 总结


前言

故障隔离的目的是对故障组件进行隔离,以避免其影响系统中的其他组件,尽可能保证分布式系统的可用性。

在分布式系统中,故障在所难免,发生故障后仅仅进行隔离还远远不够,还需要进行故障恢复。比如,现在集群中有 3 个节点,节点 1 故障后,对节点 1 进行隔离,如果节点 2、节点 3 紧接着故障了,又隔离了这两个节点。整个集群就无法继续提供服务了。

为了解决这种问题,分布式领域还有一个关键技术来保证系统的高可用,即故障恢复。

故障类型

在任何一个分布式系统中,故障都是不可避免的。故障通常包括两类:

  • 物理故障,比如硬盘损坏、断电断网、硬件升级等;
  • 软件层故障,比如系统存在 Bug 导致系统崩溃、系统负载过高导致系统崩溃等。

在讨论分布式系统故障时,通常还会从是否是网络导致的故障的角度来进行故障划分,包括节点故障和网络故障,而这两类故障可能同时包括物理故障和软件层故障。由于软件层故障和具体的程序实现等相关,因此主要由开发者根据自己的实现去解决;而物理故障通常具有很多共同特征,主要针对物理故障导致软件不可用的情况。

节点故障:单个机器自身出现故障。比如,由机器 A、B,……,Z 构成的分布式集群中,机器 A 自身出现故障,而不是非机器之间的网络连接出现故障,就是节点故障。

分布式高可用:故障恢复_第1张图片

节点故障有很多种,大体可以分为两类:

  • 硬件故障,比如机器硬盘损坏、内存接触不良等;
  • 软件故障,比如由于请求过多,超过服务器处理能力上限,导致无法处理,又或者是机器被攻击,导致机器瘫痪等。

节点故障在软件层的表现结果是,该机器无法为用户提供服务。

网络故障:分布式集群中,节点之间无法完成通信。比如,由机器 A,B, ……,Z 构成的分布式集群中,机器间比如机器 A 和 B 之间无法完成通信,就是网络故障。

分布式高可用:故障恢复_第2张图片

网络故障也有很多种,比如路由器故障、DNS 故障、网络线路断裂等。这些物理故障在软件层的表现结果是,机器间无法通信,影响分布式应用正常提供服务。

了解了故障的类型,我们还要搞明白如何检查到故障,也就是如何进行故障检测,因为这是故障恢复的前提。

故障检测

故障检测:通过一定的方式识别或发现故障。就好比把火灾、地震等危险事件看作是故障,采用火灾报警器、地震仪等来检测发现火灾或地震。

如果可以提前检测到事件的发生,就能将损失降到最小。在分布式系统中,检测硬件故障通常比较麻烦,因此会通过查看软件层的表现结果来进行故障检测。比如,网络故障导致服务器之间无法通信,因此就可以通过检测服务器之间是否可以通信(比如,服务器之间心跳包 是否可以正常地发送和接收),来检测是否存在网络故障。

故障恢复

故障恢复:修复分布式系统中出现的故障,使系统恢复正常。简单来说,故障恢复就 是故障发生之后的弥补方案,可以理解为对故障进行修正或修复,以保证服务正常运行,有点类似“知错能改,善莫大焉”。

接下来,我们就具体看看故障检测和故障恢复的原理或者说策略吧。

分布式故障检测原理

在分布式系统中,常见的故障检测方法是心跳机制。基于心跳进行故障检测的策略主要分为两类,固定心跳检测策略和根据历史心跳信息预测故障策略

通过心跳方式判断集中式架构和非集中式架构中节点是否存活的方法,用到的就是固定心跳检测策略。

基于历史心跳消息预测故障的策略,也就是 φ 值故障检测。

φ值故障检测是基于心跳间隔符合正态分布的假设进行计算的。φ值是用来评估心跳是否超时的概率,是对心跳间隔的概率求对数,将非整数转换为整数以便于理解。

φ值故障检测方法中,通常会设置一个阈值Ф,若当前心跳计算得到的 φ≥Ф,则判断心跳超时,否则心跳未超时。

从流程上来讲,φ值的计算可以分为三步:

  1. 采样窗口存储心跳到达的时间;
  2. 通过样本计算出心跳到达时间间隔的分布;
  3. 使用得到的正态分布计算当前的φ值。

第一步:采样窗口存储心跳到达的时间

采样窗口就是一个具有固定容量的容器,一般存储近 k 次的心跳信息,每次心跳到达时,会将到达时间存储到采样窗口,如果采样窗口已满,则会删除窗口中最旧的数据。

比如,采样窗口最多存储最近 10 次心跳到达的时间,t1,t2,……, t10,当第 11 次心跳到来时,采样窗口会将 t1 删除,存入 t11。到达时间的间隔很容易得到,比如第 11 次心跳到来后,到达时间的间隔是 t3 - t2,t4 – t3,……,t11 – t10。通过这些采样数据,可以计算出样本的平均值μ和方差 σ ,以便后面计算φ值。当然,随着新的心跳到来,这些数据会进行相应的更新。

第二步:通过样本计算出心跳到达时间间隔的分布

φ值故障检测是假设心跳到达时间间隔的分布遵循正态分布,假设 Plater(t) 表示接收到上一次心跳之后 t 个时间片能收到下一次心跳的概率,则通过第一步中得到的样本平均值µ和方差 σ^2 ,得到 Plater(t) 的计算结果如下:

分布式高可用:故障恢复_第3张图片

F(t) 是具有均值µ和方差 σ^2 的正态分布的累积分布函数。

第三步:使用得到的正态分布计算当前的φ值

假设,Tlast 表示最近一次接收到心跳的时间,tnow 表示当前时间。将 Tlast、tnow ,和第二步求得的 Plast(t),带入以下公式即可求得φ值:

分布式高可用:故障恢复_第4张图片

求得φ值后,与阈值Ф进行比较,即可判断节点是否发生故障。

以上就是φ值故障检测策略,基本思想是利用了历史心跳信息,来降低误判的可能性。

φ值故障检测策略可以根据历史心跳信息动态预测下一次心跳是否超时,并可以通过设置阈值来自由调控误判的可能性。目前,该策略已被应用到一些框架中,比如 Akka 集群的故障检测,便是采用了φ值故障检测策略。

故障恢复策略

对于单节点故障问题,往往采取主备策略,即当主节点故障后,从备节点中选出一个作为新的主节点,以继续提供服务。

如下图所示,用户 A 访问分布式集群时一直是与 Master 交互的,但当 Master 故障后, 其他 Slave 会通过分布式选举算法选出一个新的主节点。假设,从 Slave 1、Slave 2 和 Slave 3 中选举出 Slave 2 作为新的 Master,则 Slave 2 需要承担原来 Master 的职责,继续为用户提供服务,因此当用户 A 再次访问集群时,提供服务的是新选出的 Master,也就是 Slave 2。这就是备升主的过程。

分布式高可用:故障恢复_第5张图片

从用户 A 的角度来看,并不会感受到服务有什么异常,因为依旧可以正常访问集群。因此,主备策略可以大大提高分布式系统的可用性,在分布式系统中随处可见。比如, Redis 集群、ZooKeeper 集群等,都是采用了这种主备策略来做故障恢复。

对于网络故障问题,就是 C、A、P 选择的问题,即在分布式系统的可用性和数据一致性之间做权衡。根据不同的应用场景,选择不同的解决方案。

当分布式系统中出现网络故障时,对于高可用性要求严格的系统,比如要求必须及时响应用户的场景,就需要采用保 AP 弃 C 的策略;对于数据一致性有严格要求的系统,比如银行、金融系统等场景,就需要采用保 CP 弃 A 的策略。

网络故障恢复问题也可以看作数据复制的问题,即网络故障恢复后节点间数据同步的问题。同步复制、异步复制和半同步复制技术,半同步复制技术因为既能有效保证数据安全,又能满足系统高性能的要求,所以最受欢迎,被大多数分布式系统采用。

节点故障和网络故障也有交叉的地方,比如网络故障产生的原因可能是节点故障,即因为节点故障导致节点间无法通信,而不是纯粹的网络链路问题。这种情况有两种可能性, 一种是节点临时性故障,即一段时间后就会恢复;一种是节点永久性故障,即节点不会恢 复。针对第一种情况,只需等到故障恢复后,数据进行同步即可;第二种情况则需要备升主策略来解决。

知识扩展:固定心跳检测和基于历史心跳信息预测故障的策略,各有什么特点呢?

固定心跳检测的核心是,固定周期 T 秒发送心跳,若连续 k 次未收到心跳回复(时间 T 内),则判断心跳超时的时间为 k*T 秒。可以看出,k 和 T 的设置非常重要。

比如,对于要求秒级故障检测的场景(时延敏感性场景),则 k*T≤1s,因此需要将 T 设置 为 ms 级,比如 200ms,k 设置为 1000/200=5 次。但这样一来容易导致误判。因为判断超时的时间设置得太短,很可能是系统做内存回收或系统本身有高任务在运行导致心跳回复延后。

对于时延不太敏感的场景,k 或 T 可以设置得大一些,降低误判率,但却会增加发现故障的时间。

φ值故障检测是基于心跳间隔符合正态分布的假设,通过对历史心跳数据采样来预测当前心跳是否超时的。心跳间隔符合比较平稳或符 合规律的情况下,比较适合,但对于具有突发情况或心跳间隔无规律的场景误判率比较高。

在网络状况确定且比较稳定的场景下,大多数系统会采用固定心跳检测策略,因为其可以根据网络状况与业务场景自主设定合适的 k 和 T 值,简单有效;而当网络状况有所变化,且变化有规律的场景,则可以使用φ值故障检测策略。

总结

分布式高可用:故障恢复_第6张图片

你可能感兴趣的:(分布式技术原理与算法解析,分布式,网络,zookeeper)