-->

左耳听风_051_50_弹力设计篇之降级设计

你好,我是陈浩网名做耳朵house.那这节课呢我们来讲降级设计所谓的降级设计呢,本质上是为了解决资源不足和访问量过大的问题。

当资源和访问量出现矛盾的时候呢,在有限的资源下,为了能够扛住大量的请求,我们呢就需要对系统进行降级操作。

也就是说呢暂时牺牲掉一些东西,以保证整个系统的平稳运行。

我记得我在伦敦参与诺丁山狂欢节的时候,还有呢看阿森纳英超足球比赛的时候。

在散场的时候呢,因为人太多了,所有的公交系统啊完全免费,就是为了让人通行的更快。

而且呢早在散场前啊,场外就备着一堆的公交车和地铁了,这样呢就是为了在最短的时间内把人疏散掉。

虽然亏掉了一些钱,但是相比因为人员拥塞造成道路交通堵塞和可能出现的一些意外情况所造成的社会成本的损失。

公交免费策略啊真的是很明智的做法。

与这个类似啊,我们的系统在应对一些突发情况的时候啊,也需要这样的降级流程。

那一般来说呢我们的降级啊需要牺牲掉三个东西。

那第一个呢是降低一致性,从强抑致性变成最终一致性。

那第二个呢是停止次要功能,停止访问不重要的功能,从而释放出更多的资源。

那第三个呢是简化功能,把一些功能简化掉,比如简化业务流程,或者呢不再返回全量数据,只返回部分数据。

那首先呢我们来讲降低一致性。

我们要清楚的认识到,这世界上呢大多数系统啊并不都需要强一致性能。

那对于降低一致性,把强一致性啊变成最终一致性的做法,可以有效的释放资源,并且呢让系统运行的更快,从而可以扛住更大的流量。

那一般来说呢会有两种做法,那一种呢是简化流程的一致性,还有一种呢是降低数据的一致性。

那这里呢我先来说使用异步来简化流程。

我举个例子,比如电商的下单,交易系统,在强抑制的情况下,需要结算账单,扣除库存,扣除账户上的余额。

最后呢进行发货流程啊这一系列的操作。

那如果需要是强一致性的,那么就会非常慢啊,尤其是支付环节,可能会涉及银行方面的接口性能,就像双十一那样,银行方面出问题呢会导致支付不成功。

而订单流程啊就不能往下走。

在系统降级的时候呢,我们可以把这一系列的操作啊做成异步的快速结算订单,不占库存,然后呢把在线支付降级成用户到付。

那这样呢就能省去支付环节,然后批量处理用户的订单向用户发货。

用户呢货到付款,你来看文中,我给你展示的这张图。

一开始需要的全同步的方式呢,降级成了全异步的方式,库存从单笔强一致性啊也变成了多笔最终一致性。

那如果库存不够了,就只能根据先来后到取消订单了。

而支付呢也从最开始的下单请求时的强一致性变成了用户到付的最终一致性。

但一般来说呢功能降级啊都有可能会损害用户的体验。

所以呢最好给出友好的用户提示。

比如系统当前繁忙,您的订单已经收到,我们正努力为您处理订单中啊,我们会尽快给您发送订单,确认通知,还请见谅啊,这里的提示信息。

那接着呢我们再来说降低一致性的第二种做法,也就是降低数据的一致性。

那降低数据的一致性呢,一般来说啊会使用缓存的方式,或者呢直接就去掉数据。

比如呢在页面上不显示库存的具体数字,只显示有库存还是没有库存这两种状态。

那对于缓存来说呢,可以有效的降低数据库的压力。

把数据库的资源交给更重要的业务,那这样呢能够让系统更快速的运行。

那对于降级后的系统呢,不再通过数据库获取数据,而是通过缓存来获取数据。

那关于缓存的设计模式呢,我在中中有有一篇叫缓存更新的套路的文章。

这里呢讲述过缓存几种更新模式啊,你有兴趣的话可以去读一读。

在功能降级中呢,我们一般使用cash assign模式啊,或者read flu模式啊,也就是文中这张图展示的这个策略。

那这里呢我来解释三个名词,那第一个呢是失效啊,就是应用程序先从catch读数据。

那如果没有得到呢,就从数据库中取数据,那成功化放到缓存中。

那第二个呢是命中啊,就是应用程序从开始中取数据取到后呢返回。

呃,第三个呢是更新啊,就是先把数据存到数据库中成功后,再让缓存失效。

那read through模式啊,就是在查询操作中更新缓存。

也就是说当缓存失效的时候呢,cathe aside使用调用方负责把数据加载到缓存。

而race ruo呢则用缓存服务自己来加载,从而对应用方是透明的那前面讲的这些啊就是降低一致性的内容。

那接下来呢我们再来说降级需要牺牲掉的。

第二点啊,也就是停止次要的功能。

那停止次要的功能啊,也是一种非常有用的策略,把一些不重要的功能给暂时停止掉,让系统啊释放出更多的资源来。

比如电商中的搜索功能,用户的评论功能等等。

等待访问的峰值。

过去之后呢,我们再把这些功能啊给恢复回来。

呃,当然呢最好不要直接停止次要的功能。

呃,首先呢可以限制了次要的功能的流量,或者呢把次要的功能退化成简单的功能。

到最后啊啊如果量还是太大了,我们才会进入停止功能的状态。

那停止功能呢对用户会带来一些影响,用户体验的问题,尤其是要停掉一些,可能对于用户来说啊是非常重要的功能。

所以呢如果可能啊最好给用户一些补偿,比如把用户切换到一个送积分卡啊,或者红包抽奖的网页上,有限的补偿一下用户。

那降级设计需要新增到的第三点呢,就是要简化功能。

那关于功能的简化,前面的下单流程中已经提到过相应的例子了。

而且呢从缓存中返回数据啊也是其中一个。

那这里呢我再提一个啊,就是一般来说呢一个API啊会有两个版本,一个版本呢返回全量数据。

另一个版本呢是返回部分或者最小的可用数据。

我举个例子,对于一篇文章,一个API呢会把商品详情页啊或者文章的内容和所有的评论都返回到前端。

那么在降级的情况下呢,我们就只返回商品信息和文章内容,而不返回用户评论了。

因为用户评论啊会涉及更多的数据库操作,那这样呢就可以释放更多的数据库资源。

而商品信息或者文章信息呢可以放在缓存中,这样呢又能释放出更多的资源给交易系统,这样的需要更多数据库资源的业务来使用。

那最后呢我们来谈一谈降级设计的要点,对于降级啊,一般来说啊是要牺牲业务功能或者流程还有一致性的。

所以呢我们需要对业务做非常仔细的梳理和分析。

我们很难通过不侵入业务的方式来做到功能降级。

那在设计降级的时候呢,需要清楚的定义好降级的关键条件,比如吞吐量过大、响应时间过慢、失败次数过多,有网络或者服务故障等等。

然后呢做好相应的应急预案。

那这些预案呢最好是写成代码啊,可以快速的自动化或者半自动化执行的那功能。

降级呢需要梳理业务的功能,哪些是must have的功能,哪些呢是nice to have的功能,哪些是必须要死保的功能,哪些呢是可以牺牲的功能,而且呢需要在事前就设计好,可以简化的或者用来应急的业务流程。

那当系统出问题的时候呢,就需要走简化的应急流程。

那降级的时候呢,需要牺牲掉一致性或者一些业务流程,对于读操作来说呢,使用缓存来解决。

那对于写操作来说呢,需要异步调用来解决,并且呢我们需要以流水账的方式记录下来。

那这样呢方便对账,以免漏掉啊,或者和正常的流程混淆。

那降级的功能开关可以是一个系统的配置开关。

那做成配置的时候呢,你需要在降级的时候啊推送相应的配置。

还有一种方式呢,就是在对外服务的API上有所区分。

那这样呢可以由上游调用者来驱动。

比如说一个网关在限流的时候,在协议头中呢加入了一个限流程度的参数,让后端符啊能知道限流在发生中,当限流程度达到某个值啊,或者限流时间超过某个值的时候呢,就自动开始降级,直到限流好转。

那对于数据方面的降级呢,需要前端程序的配合。

那一般来说呢,前端的程序啊可以根据后端传来的数据来决定展示哪些界面模块。

比如当前端收不到商品评论的时候呢就不展示。

那为了区分本来就没有数据,还是因为降级了没有数据。

这两种情况呢在协议头中啊也应该加上降级的标签。

因为降级的功能平时不会总是会发生啊属于应急的情况。

所以呢降级的这些业务流程和功能都有可能长期不用,而出现bug或者问题。

所以呢需要在平时啊做一些演练。

好了,我们来总结一下今天分享的主要内容。

首先呢降级设计啊本质上是为了解决资源不足和访问量过大的问题。

那降级的方法呢有将近一致性,停止次要功能,还有简化功能。

最后呢我总结了降级设计的要点。

在下节课呢,我将总结整个弹力设计篇,希望能对你有帮助。

也欢迎你分享一下你实现过怎样的降级机制呢?有没有和限流机制配合呢?文末呢我给出了分布式系统模式系列文章的目录,希望你能在这个列表里啊找到自己感兴趣的内容。