Skip to content

高可用的本质

Published: at 10:41:45

本文系转载至公众号:阿里技术—高可用的本质 转载系列的文章都是本人觉得写得非常好的,值得认真品读学习的文章。

我是乐羊,一个热爱风险防控的人,之前参与过蚂蚁Glocal多个站点从0到1的建站和高可用建设,目前正在参与蚂蚁大安全的高可用建设。无论是一个域,一个BG,还是一个站点,虽然范围有大有小,对象有所不同,但其高可用的理念都是相通的,今天将自己对高可用的一点点思考以及总结的【nPRT公式】分享给大家。

本文采用“高可用是什么,为什么要高可用,怎么做高可用,为什么这么做,软件风险又在哪里”的逻辑来介绍。

一  高可用是一种控制风险的能力

高可用是一种面向风险设计,使系统具备控制风险,提供更高的可用性的能力。

二  为什么要高可用

对于一个公司而言,“为什么要高可用”可以完整理解为“公司为什么要(做系统)高可用”。以公司为对象,从内看包括:人,软件(物),硬件(物);从外看包括:客户,股东,社会;从自身看包括:公司。

1

高可用的大前提:所有事物都不是100%可靠的

内因:人、物都不是100%可靠的

从概率学角度分析,凡是有可能会出错的,只要变化次数足够多,最终出错的概率会无限趋向于1。

外因:无高可用,对外影响面是很大的

根因(本质):控制风险

从公司自身角度:控制风险,保障公司价值,避免伤及根本。

三  如何做高可用

如何做高可用,本质上就是:如何控制风险。

1  风险相关概念

2  风险期望的公式

根据上节的定义,可以推导出风险期望的公式如下:

2

r代表风险,风险期望会随着风险的数量n和每个风险的P、R、T下降而下降,简称nPRT公式。

注:如果要引用该公式请注明出处。

3  控制风险的4大因素(nPRT)

减少风险数量,n

从源头远离风险,做到与风险载体无连接,无关系;那么该风险概率就是0,也不关心该风险发生后的故障影响面是大是小,完全不关心。

降低风险变故障的概率**(即:增加风险变故障的难度),P**

把风险当成一个对象看待,给它层层设卡,增加风险变故障的门槛和难度,不要再让“不小心多了一个空格或字符,系统就挂了”这种惨案轻易出现。

减小故障影响范围,R

以大拆小,将一个整体拆分成N个小的个体,每个个体之间进行相互隔离,单个个体出问题仅影响单个个体,实现小而美。

缩短故障影响时长,T

故障影响时长由故障发现时间和故障止血时间决定,所以要早发现早止血。

发现方式分为:事前的预警,事后的告警。尽可能朝事前预警去做,给止血争取时间甚至将风险扼杀在摇篮中。

止血方式分为:切换,回滚,扩容,降级 or 限流,BUG修复等。故障出现时第一优先原则为快速止血(如切换、回滚、扩容),严禁去定位根因;当无法快速止血时以少流血为第二优先原则,如降级、限流。

止血效率:自动 vs 人工 ;一键化 vs 多步操作。尽可能用自动化去代替人工操作,若人工操作时尽量实现一键化,提升止血速度。

4  高可用架构设计的7大核心原则

根据nPRT公式,在高可用架构设计时有以下7个核心原则:

少依赖原则:能不依赖的,尽可能不依赖,越少越好(n)

由于所有事物都不是100%可靠的,当2个事物之间有了关系,那么就会相互影响,就互为对方的一个风险,一个出问题可能会影响另外一个。我们统一用依赖来泛指这里的“关系”。

什么场景适合多依赖?

当引入依赖(n变大)可以减小PRT中的一个或多个,且使E(r)整体下降时。

弱依赖原则:一定要依赖的,尽可能弱依赖,越弱越好(P)

事物a强依赖事物b,一旦b出问题时,那么a也会出问题,一损俱损。

所以任何强依赖都要尽可能的转化成弱依赖,可以直接降低出问题的概率。

分散原则:鸡蛋不要放一个篮子,分散风险(R)

3

打散拆分成N份;避免全局只有1份,否则一有问题影响范围就是100%。

均衡原则:均匀分散风险,避免不均衡(R)

4

最好N份中的每份都是均衡的;避免某个份额过大,否则过大的那份一有问题就影响范围过大了。

隔离原则:控制风险不扩散,不放大(R)

5

每份之间是相互隔离的;避免一份有问题影响其他的也有问题,传播扩散了影响范围。

隔离是有级别的,隔离级别越高,风险传播扩散的难度就越大,容灾能力越强。

隔离原则是一个极其重要的原则,它是前面4个原则的前提。没有做好隔离,前面4个原则都是脆弱的,风险很容易传播扩散开,破坏前面4个原则的效果。大量真实系统故障是因为隔离性做得不好导致的,如:线下影响线上,离线影响在线,预发影响生产,一条烂SQL影响整个库(或整个集群)等等。

分散,均衡,隔离是控制风险影响范围的3个核心原则。打散拆分成N份,每一份都是均衡的,且相互隔离,一份有问题,影响范围为1/N。

无单点原则:要有冗余或其他版本,做到有路可退(T)

快速止血的方式是切换,回滚,扩容等;回滚和扩容属于特殊的切换,回滚指的是切换到某个版本,扩容指的是将流量切换到新扩容的机器上。

切换得有地方可切才行,所以不能有单点(这里特指强依赖的单点,弱依赖的可以降级),要有冗余备份或其他版本;单点会限制整体的可靠性。

假设单点的可靠性假设是99.99%,它要提升到99.999%是非常困难的,但是如果无单点而是依赖2个(1个挂掉没有关系,只要不同时挂就行),那整体可靠性就是99.999999% 会有质的提升。

单点故障会导致无法快速止血,拉长整个止血时间,去单点至关重要。这里的单点不仅仅指的是系统节点,也包含人员,如订阅告警的人,应急的人等等。

对于(重要)数据节点,必须满足无单点原则,否则极端情况下可能造成数据永久丢失,永远无法恢复;(重要)数据节点满足无单点原则后,保障数据一致性比可用性要求更重要。

无单点原则和分散原则的区别:

自我保护原则:少流血,牺牲一部分,保护另外一部分(P&R&T)

外部的输入都不是100%可靠的,有时候是无意的错误,有时候甚至是恶意的破坏,因此针对外部输入要有防错设计,给自己多一些保护。

极端情况下可能无法(快速)止血,可以考虑少流血,牺牲一部分保护另外一部分。例如:限流,降级等。

四  软件风险在何方

前面介绍了控制风险的方法,回到软件系统这个领域,它的风险又在哪里?

以软件系统为对象,从内看包括:计算系统和存储系统;从外看包括:人员,硬件,上游系统,下游系统;以及(隐含的)时间。

6

由于每个对象都是由其他对象组成的,因此每个对象还可以继续往细分解(理论上可以无限分解下去),上面的分解方式主要是为了简化理解。

1  软件系统风险的来源

风险源于(有危害的)变化,一个对象的风险来源于所有跟它有关系的对象的(有危害的)变化。因此,软件系统风险的来源,分为以下7大类:

计算系统变化:运行变慢,运行错误

系统运行所依赖的服务器资源(如CPU,MEM,IO等),应用资源(RPC线程数,DB连接数等),业务资源(业务ID满了,余额不足,业务额度不够等)的负载等都会影响系统运行的风险期望。

存储系统变化:运行变慢,运行错误,数据错误

系统运行所依赖的服务器资源(如CPU,MEM,IO等),存储资源(并发数等),数据资源(单库容量,单表容量等)的负载和数据一致性等都会影响存储系统运行的风险期望。

人的变化:变更出错

变更人员的数量,安全生产意识,熟练程度,变更的数量,变更的方式等都会影响变更的风险期望。

由于变更的人多,变更的次数也多,导致变更成为蚂蚁所有故障来源里的TOP1,这也是为什么“变更三板斧”这么出名的原因。

“变更三板斧”正确的排序应该是“可灰度,可监控,可应急”;可灰度代表的是R,可监控和可应急代表的是T。

思考:如果变更三板斧让你再加一板斧,你觉得应该是什么?

硬件变化:损坏

硬件的数量,质量,使用年限,保养等都会影响硬件的风险期望,硬件损坏会影响上层软件系统不可用。

上游变化:请求变大

请求分为3个维度:(由无数API汇集而成的)网络流量,(由无数KEY请求组成的)API,KEY。

所以大促保障的时候,不仅仅是关注核心API的容量保障,还需要考虑网络流量和热点KEY。

下游变化:响应变慢,响应错误

下游服务的数量,服务等级,服务可用率等影响下游服务的风险期望。下游响应变慢可能会拖慢上游,下游响应错误可能会影响上游运行结果。

时间变化:时间到期

时间到期往往被人忽视,但它往往具有突然性和全局破坏性,一旦时间到期触发故障会导致非常被动,所以要提前识别,尽早预警,如:秘钥到期,证书到期,费用到期,跨时区,跨年,跨月,跨日等。

以上每一大类风险都可以基于nPRT公式进行逐一分析处理。

2  风险的数量:一生三,三生万物

任何一个事物既是由其他事物组成的又是其他事物的组成部分,无限循环下去;一生三,三生万物,风险的数量是无穷无尽的。

向内看,内含内,可以无限小下去;当原子粒度的问题传播开时,也可能影响软件系统的可用性,就像100纳米的新冠病毒就可以影响人体的可用性一样。

向外看,外有外,可以无限大下去;当太阳系毁灭,软件系统的可用性自然就不复存在。

虽然风险无穷无尽,但是只要我们对风险多一些了解,根据控制风险的一些理念和原则,还是可以更好的降低风险期望。

谈一谈敬畏之心:

五  结束语

nPRT公式不仅仅适用于软件系统风险,也适用于其他风险领域,希望对大家有用。