10 KiB
隔离设计对应的单词是Bulkheads,中文翻译为隔板。但其实,这个术语是用在造船上的,也就是船舱里防漏水的隔板。一般的船无论大小都会有这个东西,大一点的船都会把船舱隔成若干个空间。这样,如果船舱漏水,只会进到一个小空间里,不会让整个船舱都进水而导致整艘船都沉了,如下图所示。


我们的软件设计当然也“漏水”,所以为了不让“故障”蔓延开来,需要使用“隔板”技术,来将架构分隔成多个“船舱”来隔离故障。
多扯一句,著名的泰坦尼克号也有Bulkheads设计,然而其设计上有个缺陷。如下图所示,当其撞上冰山漏水时,因为船体倾斜,导致水漫过了隔板,从而下沉了。

在分布式软件架构中,我们同样需要使用类似的技术来让我们的故障得到隔离。这就需要我们对系统进行分离。一般来说,对于系统的分离有两种方式,一种是以服务的种类来做分离,一种是以用户来做分离。下面具体说明一下这两种方式。
按服务的种类来做分离
下面这个图中,说明了按服务种类来做分离的情况。

上图中,我们将系统分成了用户、商品、社区三个板块。这三个块分别使用不同的域名、服务器和数据库,做到从接入层到应用层再到数据层三层完全隔离。这样一来,在物理上来说,一个板块的故障就不会影响到另一板块。
在亚马逊,每个服务都有自己的一个数据库,每个数据库中都保存着和这个业务相关的数据和相应的处理状态。而每个服务从一开始就准备好了对外暴露。同时,这也是微服务所推荐的架构方式。
然而任何架构都有其好和不好的地方,上面这种架构虽然在系统隔离上做得比较好,但是也存在以下一些问题。
也就是说,先做一个plan的API调用,然后各个子系统reserve住相应的资源,如果成功,则Commit;如果有一个失败,则整体Cancel。这其实很像阿里的TCC – try confirm/cancel。
可见,隔离了的系统在具体的业务场景中还是有很多问题的,是需要我们小心和处理的。对此,我们不可掉以轻心。根据我的经验,这样的系统通常会引入大量的异步处理模型。
按用户的请求来做分离
下图是一个按用户请求来做分离的图示。

在这个图中,可以看到,我们将用户分成不同的组,并把后端的同一个服务根据这些不同的组分成不同的实例。让同一个服务对于不同的用户进行冗余和隔离,这样一来,当服务实例挂掉时,只会影响其中一部分用户,而不会导致所有的用户无法访问。
这种分离和上面按功能的分离可以融合。说白了,这就是所谓的“多租户”模式。对于一些比较大的客户,我们可以为他们设置专门独立的服务实例,或是服务集群与其他客户隔离开来,对于一些比较小的用户来说,可以让他们共享一个服务实例,这样可以节省相关的资源。
对于“多租户”的架构来说,会引入一些系统设计的复杂度。一方面,如果完全隔离,资源使用上会比较浪费,如果共享,又会导致程序设计的一些复杂度。
通常来说多租户的做法有三种。
这三种方案各有优缺点,如图所示。

通过上图,可以看到:
所以,一般来说,技术方案会使用折衷方案,也就是中间方案,服务是共享的,数据通过分区来隔离,而对于一些比较重要的租户(需要好的隔离性),则使用完全独立的方式。
然而,在虚拟化技术非常成熟的今天,我们完全可以使用“完全独立”(完全隔离)的方案,通过底层的虚拟化技术(Hypervisor的技术,如KVM,或是Linux Container的技术,如Docker)来实现物理资源的共享和成本的节约。
隔离设计的重点
要能做好隔离设计,我们需要有如下的一些设计考量。
小结
好了,我们来总结一下今天分享的主要内容。首先,我从船体水密舱的设计,引出了分布式系统设计中的隔离设计。然后我介绍了常见的隔离有两种,一种是按服务种类隔离,另一种是按用户隔离(即多租户)。下篇文章中,我们讲述异步通讯设计。希望对你有帮助。
也欢迎你分享一下你是如何为分布式系统做隔离设计的。
文末给出了《分布式系统设计模式》系列文章的目录,希望你能在这个列表里找到自己感兴趣的内容。
-
- [认识故障和弹力设计](https://time.geekbang.org/column/article/3912)
- [隔离设计Bulkheads](https://time.geekbang.org/column/article/3917)
- [异步通讯设计Asynchronous](https://time.geekbang.org/column/article/3926)
- [幂等性设计Idempotency](https://time.geekbang.org/column/article/4050)
- [服务的状态State](https://time.geekbang.org/column/article/4086)
- [补偿事务Compensating Transaction](https://time.geekbang.org/column/article/4087)
- [重试设计Retry](https://time.geekbang.org/column/article/4121)
- [熔断设计Circuit Breaker](https://time.geekbang.org/column/article/4241)
- [限流设计Throttle](https://time.geekbang.org/column/article/4245)
- [降级设计degradation](https://time.geekbang.org/column/article/4252)
- [弹力设计总结](https://time.geekbang.org/column/article/4253)