乐趣区

关于设计:进来抄作业分布式系统中保证高可用性的常用经验

摘要:高可用性对于咱们来说应该属于常常提到的名词,本文咱们将介绍在分布式系统中保障高可用性的一些罕用教训。

高可用性对于咱们来说应该属于常常提到的名词,本文咱们将介绍在分布式系统中保障高可用性的一些罕用教训。

零碎可用性指标

零碎可用性指标简略来将就是零碎可用工夫与总运行工夫之比

Availability=MTTF/(MTTF+MTTRMTTF)

​MTTF 是 Mean Time To Failure,指均匀故障前的工夫,即零碎均匀可能失常运行多长时间才产生一次故障。零碎的可靠性越高,MTTF 越长(简略了解 MTTF 就是指零碎失常运行的工夫)。MTTR 是 Mean Time To Recovery,均匀修复工夫,即从故障呈现到故障修复的这段时间,也就是零碎不可用的工夫,这段时间越短越好。零碎可用性指标能够用通过下表的 999 规范掂量,当初广泛要求至多 2 个 9,最好 4 个 9 以上:

故障不可避免

高可用性是指零碎提供的服务要始终可用,然而故障不可避免,特地是在分布式系统,面对不可控的用户流量和机房环境,系统故障将会显得更加简单和不可预测。在大规模的分布式系统中,各个模块之间存在盘根错节的依赖,任一一个环节呈现问题,都有可能导致雪崩式、多米诺骨牌式的故障,甚者能够断言呈现故障成了常态。

如上图的分布式系统中,用户申请零碎中的某个服务接口,申请须要通过长长的调用链能力解决返回。咱们起码要保障网络连接失常,服务网关失常、前端服务失常、后盾服务失常、数据库失常,申请能力被失常解决,如果调用链中的任一环节呈现问题,都会间接反馈到用户体验上。

零碎呈现故障的起因多种多样,次要有以下这些:

  • 网络问题,网络连接故障,网络带宽呈现超时拥塞等;
  • 性能问题,数据库慢查问、Java Full GC、硬盘 IO 过大、CPU 过高、内存不足等
  • 平安问题,被网络攻击,如 DDoS 等、异样客户端申请,如爬虫等。
  • 运维问题,需要变更频繁不可控,架构也在一直地被调整,监控问题等;
  • 治理问题,没有梳理出要害服务以及服务的依赖关系,运行信息没有和控制系统同步;
  • 硬件问题,硬盘损坏、网卡出问题、交换机出问题、机房掉电、挖掘机问题 (前一阵子机房电缆就常常被挖断) 等

面对如此多的天下大乱,可控和不可控的故障因素,仿佛零碎的高可用性变成不可能实现的工作,然而在日常开发运维中,咱们能够采纳一些无效的设计、实现和运维伎俩来进步零碎的高可用性,尽量交付一个在任何时候都根本可用的零碎。

冗余设计

分布式系统中单点故障不可取的,而升高单点故障的不二法门就是冗余设计,通过多点部署的形式,并且最好是部署在不同的物理地位,防止单机房中多点同时失败。冗余设计不仅能够进步服务的吞吐量,还能够在呈现劫难时疾速复原。目前常见的冗余设计有主从设计和对等治理设计,主从设计又能够细分为一主多从、多主多从。

冗余设计中一个不可避免的问题是思考分布式系统中数据的一致性,多个节点中冗余的数据谋求强一致性还是最终一致性。即便节点提供无状态服务,也须要借助内部服务,比方数据库、分布式缓存等保护数据状态。依据分布式系统下节点数据同步的基本原理 CAP(Consistency (一致性)、Availablity (可用性)、Partition tolerance (分区容忍性)三个指标不可同时满足),数据强一致性的零碎无奈保障高可用性,最典型的例子就是 Zookeeper。

Zookeeper 采纳主从设计,服务集群由 Leader、Follower 和 Observer 三种角色组成,它们的职责如下:

  • Leader: Zookeeper 集群应用 ZAB 协定通过 Leader 选举从集群中选定一个节点作为 Leader。Leader 响应客户端的读写申请;
  • Follower:只提供数据的读服务,会将来自客户端的写申请转发到 Leader 中。在 Leader 选举的过程中参加投票,并与 Leader 维持数据同步;
  • Observer:与 Folllower 的性能雷同,但不参加 Leader 选举和写过程的 ” 过半写胜利 ” 策略,单纯为了进步集群的读能力。

在 Zookeeper 集群中,因为只有 Leader 角色的节点具备写数据的能力,当 Leader 节点宕机时,在新的 Leader 节点没有被选举进去之前,集群的写能力都是不可用的。尽管 Zookeeper 保障了集群数据的强一致性,然而放弃了集群的高可用性。

对等治理设计中比拟优良的业内体现为 Netiflx 开源的 Eureka 服务注册和发现组件。Eureka 集群由 Eureka Client 和 Eureka Server 两种角色组成,其中 Eureka Client 是指服务实例应用的服务注册和发现的客户端,用于注册和查问服务实例信息;Eureka Server 作为服务注册核心,存储有各服务的实例信息列表,采纳多实例的形式部署保障高可用性。每一个 Eureka Server 都是对等的数据节点,Eureka Client 能够向任意的 Eureka Server 发动服务注册申请和服务发现申请。Eureka Server 之间的数据通过异步 HTTP 的形式同步,因为网络的不可靠性,不同 Eureka Server 中的服务实例数据不能保障在任意工夫节点都相等,只能保障在 SLA 承诺工夫内达到数据的最终一致性。Eureka 点对点对等的设计保障了服务注册与发现核心的高可用性,然而就义了数据的强一致性,降级为数据的最终一致性。

熔断设计

在分布式系统中,一次残缺的申请可能须要通过多个服务模块的通力合作,申请在多个服务中传递,服务对服务的调用会产生新的申请,这些申请独特组成了这次申请的调用链。当调用链中的某个环节,特地是上游服务不可用时,将会导致上游服务调用方不可用,最终将这种不可用的影响扩充到整个零碎,导致整个分布式系统的不可用,引发服务雪崩景象。

为了防止这种状况,在上游服务不可用时,爱护上游服务的可用性显得极其重要。对此,咱们能够参考电路系统的断路器机制,在必要的时候壮士断腕,当上游服务因为过载或者故障不能用时,及时“熔断”服务调用方和服务提供方的调用链,爱护服务调用方资源,避免服务雪崩景象的呈现。

断路器的根本设计图如下,由敞开、关上、半开三种状态组成:

  • 敞开 (Closed) 状态:此时服务调用方能够调用服务提供方。断路器中应用失败计数器周期性统计申请失败次数和申请总次数的比例,如果最近失败频率超过了周期时间内容许失败的阈值,则切换到关上 (Open) 状态。在敞开状态下,失败计数器基于工夫周期运作,会在每个统计周期开始前主动重置,避免某次偶尔谬误导致断路器进入关上状态。
  • 关上 (Open) 状态:在该状态下,对应用程序的申请会立刻返回谬误响应或者执行预设的失败降级逻辑,而不调用服务提供方。断路器进入关上状态后会启动超时计时器,在计时器达到后,断路器进入半开状态。

半开 (Half-Open) 状态:容许应用程序肯定数量的申请去调用服务。如果这些申请对服务的调用胜利,那么能够认为之前导致调用失败的谬误曾经修改,此时断路器切换到敞开状态,同时将失败· 计数器重置。如果这肯定数量的申请存在调用失败的状况,则认为导致之前调用失败的问题依然存在,断路器切回到关上状态,并重置超时计时器来给零碎肯定的工夫来修改谬误。半开状态可能无效避免正在复原中的服务被忽然而来的大量申请再次打垮。

应用断路器设计模式,可能无效地爱护服务调用方的稳定性,它可能防止服务调用者频繁调用可能失败的服务提供者,避免服务调用者节约 CPU 周期、线程和 IO 资源等,进步服务整体的可用性。

小结

本文次要介绍了几种高可用的设计,除了下面介绍的形式之外,还无限流设计和一些其余设计与计划,如降级设计、无状态设计、幂等性设计、重试设计、接口缓存、实时监控和度量以及常布局化保护。

本文分享自华为云社区《分布式系统如何保障高可用性?(上)》,原文作者:aoho。

点击关注,第一工夫理解华为云陈腐技术~

退出移动版