从反脆弱角度谈技术系统的高可用性

共 2773字,需浏览 6分钟

 ·

2020-12-10 02:06

1 非线性

我们先来介绍一个概念:非线性。这个概念在我们的生活中无处不在。

你要赶早上8点钟的火车,如果6:30出发可以在7:00到达车站,于是你得到一个结论:只要30分钟就可以到达车站。

你早上想睡晚一点预计7:10出发,想着7:40可以到达车站。但是最可能的结果是你将错过这趟火车。因为正好遇上早高峰,堵车导致你至少需要花费1个小时才能到达车站。

一个小雪球的重量是100克,打雪仗时你被砸中100次,这对你不会造成任何影响。

但是如果你被10公斤的雪球砸中1次,这可能会对你造成严重的伤害。

这就是非线性。事物不是简单叠加关系,当达到某个临界值时会造成一种完全截然不同的结果。


2 秒杀系统

我们来分析一个互联网的秒杀场景。假设你设计的秒杀系统当每秒30个人访问时,响应时间是10毫秒。即从用户点击按钮至得到结果这个过程,只花费了10毫秒。这个时间的流逝基本上察觉不到,性能是不错的。你感觉很好,继续设计:

每秒30个访问量响应时间10毫秒

每秒300个访问量响应时间100毫秒

每秒3000个访问量响应时间1000毫秒

如果你按照这个思路去做系统设计,将会发生重大的错误。因为当每秒3000个访问量发生时,系统的响应时间可能不是1000毫秒,而可能直接导致系统崩溃,无法再处理任何的请求。最常见的场景就是当缓存系统失效时,导致的系统雪崩:

  • 当耗时低的缓存层出现故障时,流量直接打在了耗时高的数据库层,用户的等待时长就会增加

  • 等待时长的增加导致用户更加频繁去访问,更多的流量会打在数据库层

  • 这导致用户的等待时长进一步增加,再次导致更频繁访问

  • 当访问量达到一个极限值时,造成系统崩溃,无法再处理任何请求

流量和响应时间绝不是简单的叠加关系,当到达某个临界值时,系统将直接崩溃。


3 黑天鹅与三体

欧洲人从来都认为只有白天鹅,因为他们从来只看到过白色的天鹅。

他们的这种想法有多坚定,那他们在澳大利亚发现黑色天鹅时,震撼就有多么大。

这就是著名的黑天鹅事件的由来。黑天鹅事件指事前无法预知,一旦发生将具有巨大影响的不确定事件。

我们来分析一下欧洲人的白天鹅理论。他们采用的是归纳推理的方法,这也是科学实验中常用的一种方法。

当他们没有见到黑天鹅之前,认为只存在白色天鹅是成立的。但当黑天鹅出现时,整个认知瞬间土崩瓦解。

一个更加值得关注的系统是混沌系统。这个系统最大的特点是,当一个微小的扰动发生时,会给整个系统带来巨大的影响。典型混沌系统的体现就是蝴蝶效应和三体问题。

一只蝴蝶挥动翅膀可以带来一场飓风。三个天体在相互的万有引力作用下,运动轨迹无法预测,这也是刘慈欣《三体》三部曲的基础设定。

处于混沌系统,不知道黑天鹅事件将在什么时间,什么地方,以什么形式发生。

我们不知道7点钟出发会被堵多久,不知道秒杀系统在开抢的瞬间会有多大的访问量。


4 工程系统稳定性

我们来思考一个问题:怎样保证一个工程系统的稳定性?有以下两种做法:

  • 思路1:考虑到所有意外情况,针对每一个意外的异常情况分别处理

  • 思路2:接受无法预料到所有意外情况的现实,把兜底方案做好,保证即使出现极端情况,系统也不会崩溃

我们仔细分析思路1会发现这其实是一个悖论。

所谓意外情况就是意料之外的情况,无法预料的情况。如果被考虑到了,那么也就不能称之为意外情况了。

塔勒布在经典著作《反脆弱》一直想告诉我们:黑天鹅事件是无法预测的,极端意外情况是无法预测的,尾部风险虽然概率小但破坏力却极大。

我们无法预测会发生什么故障,以及什么时候发生。但面对不确定性,我们不会束手就擒,至少可以把系统保护好。


5 高可用策略

为了保证系统的稳定性和高可用性,我们需要采取一些策略。我认为高可用核心策略一般包含:冗余+自动故障转移策略,降级策略,延时策略,隔离策略。高可用实际应用方案多种多样,但一般都在实施上述策略,从而构建一个稳定的高可用工程系统。


5.1 冗余 + 自动故障转移策略

最基本的冗余策略就是主从模式。原理是准备两台机器,部署了同一份代码,在功能层面是相同的,都可以对外提供相同的服务。

一台机器启动提供服务,这就是主服务器。另一台机器启动在一旁待命,不提供服务,随时监听主服务器的状态,这就是从服务器。当发现主服务器出现故障时,从服务器立刻替换主服务器,继续为用户提供服务。

自动故障转移策略是指当主系统发生异常时,应该可以自动探测到异常,并自动切换为备用系统。不应该只依靠人工去切换成,否则故障处理时间会显著增加。


5.2 降级策略

所谓降级策略,就是当系统遇到无法承受的压力时,选择暂时关闭一些非关键的功能,或者延时提供一些功能,把此刻所有的资源都提供给现在最关键的服务。

在秒杀场景中,下订单就是最核心最关键的功能。当系统压力将要到达临界值时,可以暂时先关闭一些非核心功能如查询功能。

当秒杀活动结束后,再将暂时关闭的功能开启。这样既保证了秒杀活动的顺利进行,也保护了系统没有崩溃。

还有一种降级策略,当系统依赖的下游服务出现错误,甚至已经完全不可用了,那么此时就不能再调用这个下游服务了,否则可能导致雪崩。所以直接返回兜底方案,把下游服务直接降级。


5.3 延时策略

用户下订单成功后就需要进行支付。

假设秒杀系统下订单每秒访问量是3000,我们来思考一个问题,有没有必要将每秒3000次访问量的压力传递给支付服务器?

答案是没有必要。

因为用户秒杀成功后可以稍晚付款,比如可以跳转到一个支付页面,提示用户只要在10分钟内支付完成即可。

这样每秒3000次访问量就被分摊至几分钟,有效保护了系统。技术架构还可以使用消息队列做缓冲,让支付服务按照自己的能力去处理业务。


5.4 隔离策略

物理隔离:应用分别部署在不同物理机、不同机房,资源不会互相影响。

线程隔离:不同的请求进行分类,交给不同线程池处理,当一类请求出现高耗时和异常,不影响另一类请求访问。


6 无所不备则无所不寡

《孙子兵法》虚实篇告诉我们一个道理:备前则后寡,备后则前寡,备左则右寡,备右则左寡,无所不备,则无所不寡。

力量集中在前,后面就空虚。力量集中在后,前面就空虚。力量集中在左,右面就空虚。力量集中在右,左面就空虚。如果力量分散在前后左右,那么前后左右就都空虚。

不确定性分散在前后左右无法预测。我们不可能将精力分散在前后左右,但是技术人员至少可以做好一点:保护好系统。



JAVA前线 


欢迎大家关注公众号「JAVA前线」查看更多精彩分享,主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等,同时也非常欢迎大家加我微信「java_front」一起交流学习


浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报