高可用系统的一些基本概念
近期被问及高可用系统的一些概念,但是没有系统地整理过这些概念,诸如什么是高可用系统,什么是SLA,怎么定义几个9等,所以整理一篇CheatSheet短文,系统性地掌握一下高可用的一些概念。
一、高可用的定义
Wiki对高可用系统的描述是这样的
High availability (HA) is a characteristic of a system which aims to ensure an agreed level of operational performance, usually uptime, for a higher than normal period.
其实这个概念很模糊,高本来就是相对低而言的,所以高可用是在一个约定可接受的服务能力级别基础上的一个higher than normal的概念,没有约定量化的话,就没有办法衡量。
说人话就是,可用性是系统不间断对外提供服务的能力,那么肯定的是,这种能力越强,其可用性越高,相对‘约定’来说,这就是高可用系统。
如果用一个公式来表达的话,类似这样:
可 用 性 = < 可 用 时 长 > < 可 用 时 长 > + < 故 障 时 长 > 可用性 = \frac {<可用时长>} {<可用时长>+<故障时长>} 可用性=<可用时长>+<故障时长><可用时长>
这是一个较为抽象的表达,那么当面对实际应用时,我们需要十分明确的阐明,什么是可用、什么是故障,才能够进行量化。
可用
对于不同的系统,可用代表的含义不同。对于一个运行在主机上,提供多个接口的服务。对于机房来说,主机系统正常、硬件正常、供电正常,可视为可用;对于SRE来说,可能需要主机上的系统配置正确、Side car服务运行正常等才视为可用;而对于业务团队来说,需要业务功能正常,逻辑正确,才算可用。
放大来看,对于业务团队,也要看是哪种业务,有的业务只要有部分核心接口正常工作,就可以视为服务可用;而有些业务,需要服务的所有功能都正常工作,才能视为可用,还有些业务不仅要求功能可用,还有一些性能上的要求。
这就是服务级别协商(SLA - Service Level Agreement)的概念,我们维护的服务不能简单的自己评价其可用性,而是与下游达成这样的约定,低于约定的这个水准,你的服务对于下游将变得没有价值,甚至对下游是危险的。
故障
从工业角度讲,故障就是失去产品规定功能的情况。还需要考虑具体上下文,比如网络连通,但是功能缺失,那么从网络运营方看是没有故障的,从业务运营方看就是有故障的,所以说故障时,需要统一上下文。此外,这里讲的故障,需要是可恢复的,否则讨论故障将变得没有意义。
另外,还有一些行为在外部看来是故障,实际是计划操作的一部分,比如对系统的维护、软件升级、更新软件部署等行为,这是需要约定的一部分。
那么如何设计系统,可以提升可用性呢?wiki上给出了这样三原则:
二、提升可用性的三条原则
有三条原则可以帮助系统提升可用性
- 消除单点故障 (Elimination of single points of failure(SPOF))
- 可靠的交叉点服务 (Reliable crossover)
- 提前检测故障并快速恢复 (Detection of failures as they occur)
1. 消除单点故障
Elimination of single points of failure(SPOF)
单点故障很好理解,服务没有备份,宕机就停止服务了,数据没有备份,删除就消失了,单引擎飞机出现故障显然是致命的。
2. 可靠的交叉点服务
Reliable crossover
交叉点是指无法去状态、不容易冗余的一些节点,比如DNS、消息队列。一架飞机的通讯故障可能影响范围尚小,而如果繁忙的机场塔台通讯系统一旦出现故障,那将是灾难性的,所以其必须足够可靠。
3. 提前检测故障并快速恢复
Detection of failures as they occur
提前检测故障比较倾向于运维侧,主要是对系统状态的监控,以及故障的人工/自动化恢复,以达到早发现、早治疗的目标。
三条原则都是在提升其正常服务的时间长度,减少或缩短故障出现的几率及持续时长,也呼应了高可用的定义。虽然看起来简单但应用起来却不是寥寥几句可以概括的,同时可能会带来side effect,这也是高可用设计需要面临的挑战。
三、高可用面临的挑战
状态一致性
消除单点故障一般的做法是引入冗余,对于无状态的服务,冗余十分好用,但是一旦服务有状态,情况就会变得复杂。
例如,主备冗余的系统中,数据是否要保持一致?主备之间如何同步数据?是数据过程是Sync的还是Async的?如果是Sync进行的,那么因此带来的性能下降能否承受?当主节点故障时,客户端如何failover到备用节点的?如果该主从节点是分布式系统中的一个partition,分布式集群如何做到状态一致?…
这些里面问题每一条都可以单开话题来讲。
故障的快速恢复
俗话说没有不出问题的系统,出现问题能够快速恢复也是高可用的重要一环。故障恢复也包含很多展开话题,例如,对故障的检测与发现,如果不能及时发现故障,也就谈不上快速恢复了。
当发生故障时切忌进行根因调查,应以快速恢复或回滚到上一状态为主,尽量保留问题调查的材料。
平时也应该对可能出现的故障进行演练,总结出一套应对常见问题的预案,依据预案制定相关的自动化、一键化故障恢复流程,减少故障恢复过程中的人为误操作因素。
四、可用性的量化
平均故障间隔时间(MTBF)
指所有两次故障之间的uptime时间的均值,说人话就是,所有服务可用时间段的平均值。它的计算结果是一个时间段T,表示系统每隔大约T时间,就会出现故障。设出现故障间隔区间有m个,则有:
M
T
B
F
=
∑
i
=
1
m
T
u
p
m
MTBF = \frac {\sum_{i=1}^{m} Tup} {m}
MTBF=m∑i=1mTup
平均修复间隔时间(MTTR)
指所有故障修复时间的均值,计算结果也是一个时间段T,表示系统的每次故障持续事件为T。设出现故障的区间有n个,则有:
M
T
T
R
=
∑
i
=
1
n
T
d
o
w
n
n
MTTR = \frac {\sum_{i=1}^{n} Tdown} {n}
MTTR=n∑i=1nTdown
可用性计算公式
通常可用性用以下公式计算而来:
A
=
M
T
B
F
M
T
B
F
+
M
T
T
R
A = \frac { MTBF } { MTBF+MTTR }
A=MTBF+MTTRMTBF
其中可以将A看做一个可用性的百分比值,比值中前导9的个数,即平常经常能听到的,可用性为几个9,比如A = 99.93%,那么可用性就是3个9,同理,对于几个9的阐述,也需要结合对SLA明确定义的上下文来看。
可用性计算示例
以一个实例来说明,假设有这样一个系统,其运行情况如下:
- 可用区间:[0,30), [32,95), [98,173)
- 不可用区间:[30,32), [95, 98)
那么根据MTBF、MTTR公式可得:
M
T
B
F
=
(
30
+
63
+
75
)
/
3
=
168
/
3
=
56
M
T
T
R
=
(
2
+
3
)
/
2
=
5
/
2
=
2.5
MTBF = (30+63+75)/3 = 168/3 = 56 \\ MTTR = (2+3)/2 = 5/2 = 2.5
MTBF=(30+63+75)/3=168/3=56MTTR=(2+3)/2=5/2=2.5
则可用性A为
A
=
56
/
(
56
+
2.5
)
=
95.72
%
A = 56/(56+2.5) = 95.72\%
A=56/(56+2.5)=95.72%
根据计算在173时间单位内,仅有5个时间单位出现故障的话,可用性仅有1个9,可见将可用性提升至4个、5个9,还是相当困难的,它会对系统的可靠性、故障检测、故障恢复等多方面提出非常高的要求。
Conclusion
本文总结了构建高可用系统需要关注的一些基本概念和要素。对于构建高可用系统,一般的过程如下:
-
首先就需要确定可衡量的可用性定义,这是与上下游协商的结果,协商的内容包括我们提供的服务在什么状态下是可用的,在什么状态下不可用,这一步决定了构成MTBF、MTTR的关键指标。
-
在确定了关键指标定义后,需要围绕我们的服务,建立相关指标的收集与统计机制,比如用sar来收集系统信息,用prometheus监控服务内指标,如上游响应时长,关键逻辑耗时等。这些将作为计算可用性的来源数据。
-
还需要建设关键指标的检测和告警系统,以及自动化/半自动化的故障恢复工具,通过缩短故障的恢复时间提升系统可靠性。
-
最后要建立长效的故障学习和复盘制度,通过正面反馈,优化服务自身的可靠性、完善系统面对故障时的预案,形成良性闭环。
以上就是对可用性的一些基本概念的介绍,但是可用性上可以探讨的内容很多,虽然这部分内容对于开发同学可能比较枯燥,但作为偏工程属性的工程师,可用性基本概念还是需要了解的,否则自己开发的系统也就无可用性可言。
文献
1.High availability by Wiki
2.Reliability and availability basics
3.关于高可用的系统 by coolshell