高可用,英文单词 High Availability,缩写 HA,它是分布式系统架构设计中一个重要的度量。业界通常用多个 9 来衡量系统的可用性,如下表:
既然有可用率,有一定会存在不可用的情况。系统宕机一般分为有计划的和无计划的,有计划的如日常维护、系统升级等,无计划的如设备故障、突发断电等。我们对此作如下分类:
1.设备故障:机房断电、硬盘损坏、交换机故障。
2.网络故障:网络带宽拥堵、网络连接中断。
3.安全问题:利用系统漏洞进行网络攻击。
4.性能问题:CPU 利用率太高、内存不足、磁盘 IO 过载、数据库慢 SQL。
5.升级维护:由于业务变更或技术改进而引起的系统升级。
6.系统问题:分布式系统中存在服务的依赖而导致数据的不一致性,或是核心服务出现异常。
负载均衡(Load Balance),它将工作任务分发到多个工作单元上进行运行,它可以提高网络设备的带宽,提升网络数据处理能力,增强网络的稳定性。可防止机房断电、网络设备故障等问题。
负载均衡的实现可分为硬件负载与软件负载。硬件负载由专门的设备完成专门的任务,这种方式性能较高同时成本也高;软件负载通过软件代码实现,此种方式耗费操作系统资源,性能较低,容易出现 BUG,也容易引起安全问题。
负载策略一般有轮询策略、随机策略、最小连接策略以及最短响应时间策略。
轮询策略:讲用户请求轮流分配给服务器,这种算法比较简单。
随机策略:随机选择一台服务器来执行任务。
最小连接策略:把请求分配给活动连接数最小的后端服务器。
最短响应时间策略:将请求分配给平均响应时间最短的服务器。
限流就是避免服务过载,随着流量的提高,无论负载策略如何高效,系统的某个环节总会过载。就如木桶能装多少水取决于最短的那块木板,我们是无法保证系统的每个部分都保持同样的高吞吐量,因此要考虑如何优雅地提供有损服务。
常用的三种限流算法:计数器算法、滑动窗口算法、漏桶算法、令牌桶算法。
计数器算法:使用计数器在一定周期内累加某个接口的访问次数,当达到限流阈值时,触发限流策略,进入下一个周期后,重新开始计数。此算法较为简单,但会降低服务器的负载能力。
滑动窗口算法:将时间周期划分成更小的周期,按小周期来进行计数,根据时间滑动删除过期的小周期。这种算法使得周期划分得越小服务器的负载能力越高。
漏桶算法:将请求直接放入漏桶中,如果当前访问量超出漏桶的限流值,则把后来的请求予以丢弃,这样可以最大限度地提高服务器的负载能力。
令牌桶算法:以(时间周期/限流值)的速度向令牌桶里增加令牌,直到装满桶的容量,当请求到达时,分配一个令牌让其通过,如果没有获取到令牌则触发限流机制。
### 异步调用
异步调用一般有两种方式:一种是异步回调,一种是消息队列。消息队列方式也算是限流的一种手段,可以让请求一个一个地被处理,避免并发太高而引起的应用无法及时处理。这种方式相对与限流来讲,是一种无损的解决方案。但这种方案仅适用于非实时响应的业务。
### 超时重试与幂等设计
很多文章把超时重试与幂等设计分开来讨论,但我却认为它们是相辅相成,密切相关的。在设计超时重试时,一定要考虑幂等设计
超时重试机制:由于服务器宕机、网络延时、服务器线程死锁等原因,导致应用程序无法先限定时间内对服务调用方进行响应。因此当发生调用超时后,应用程序可根据调度策略进行重试。被调用的服务没有及时响应,可能会存在两种情况,一是服务内部发生异常,导致执行失败,没有返回任何消息;一是执行的服务耗时太长,没有及时响应,但实际已经执行成功。所以针对第二种情况要做幂等设计。
幂等设计:多次相同参数的请求对系统造成的作业都是相同的。常见的幂等方案有:MCVV 多版本并发、唯一索引、token 机制、悲观锁、状态机幂等、只读操作等。
服务降级与服务熔断都是为了解决服务雪崩的问题,但不要把他们混为一谈,它们是有本质区别的。
降级是对系统的某个功能进行降级,可以只提供部分功能也可以完全停止该功能。降级一般由开关来进行控制,在不重启服务的情况下,对功能进行降级。它常常发生在高并发时段、机器卡顿、下游不太重要的服务异常等情况下。
熔断没有开关,它是一个框架级的设计,常常被称作断路器。它的主要作用是,当下游的服务因为某种原因变得不可用或服务不及时,为了保证整体服务的可用性,不再调用目标服务,直接返回默认处理或容错处理,从而使得整体服务可以快速响应。例如 SpringCloud 中的 Hystrix。
降级与熔断的主要区别是手动与自动。降级主要是通过配置中心的热刷新功能,人为地对开关进行打开与关闭操作。而熔断则是根据事先设计好的策略,系统自动地根据策略来进行开关操作。但它们都是对功能进行关闭。
实际是一主多备,master 负责提供读写服务,slave 作为数据备份,一旦主机宕机,将其中一个备节点作为主节点。
实际是一主多从,master 对外提供读写服务,slave 作为数据备份提供只读服务。主机定期复制数据给从机。多副本的关键问题是保证数据一致性,通常需要考虑数据同步延时的问题。
集群分片是为了解决每台机器上存储全量数据的问题,面对大数据单机的存储量总是有上限的,当面对 PB 级数据时,单机是无法支撑的,因此就需要对数据进行分片。
异地就是指在地理位置上不同的地方,可分为同城异地、跨城异地、跨国异地,多活就是指不同地理位置上的系统都能够提供服务。这种架构的复杂度较高,且部署成本也会提高。
设计原则:
1、 只把核心业务设计为异地多活,比如流量大、盈利高的业务
2、 保证核心数据的一致性与实时性,且可丢失、可恢复
3、 可采用多种数据同步的方案,比如存储系统同步、消息队列同步
4、 异地多活仅适用于大部分用户,以地区来论,覆盖主要城区
在互联网架构设计中,高可用是必不可少的环节,要从网络架构、服务架构、数据架构以及软硬件架构等多方面来分析设计,是架构师必备的技能之一。
作者:京东零售 谷伟
来源:京东云开发者社区