分布式系统之容错设计-故障隔离

容错设计又叫弹力设计,其中着眼于分布式系统的各种“容忍”能力,包括容错能力(服务隔离、异步调用、请求幂等性)、可伸缩性(有 / 无状态的服务)、一致性(补偿事务、重试)、应对大流量的能力(熔断、降级)。可以看到,在确保系统正确性的前提下,系统的可用性是弹力设计保障的重点。

故障隔离

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

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

按服务的种类来做分离

下面这个图中,说明了按服务种类来做分离的情况。

上图中,我们将系统分成了用户、商品、社区三个版块。三个板块分别使用不同的域名、服务器和数据库,做到从接入层到应用层再到数据层三层完全隔离。这样一来,在物理上来说,一个版块的故障就不会影响到另一版块。

按用户的请求来做分离

下图是一个按用户请求来做分离的图示。

在这个图中,可以看到,我们将用户分成不同的组,并把后端的同一个服务根据这些不同的组分成不同的实例。让同一个服务对于不同的用户进行冗余和隔离,这样一来,当服务实例挂掉时,只会影响其中一部分用户,而不会导致所有的用户无法访问。

这种分离和上面按功能的分离可以融合。说白了,这就是所谓的“多租户”模式。对于一些比较大的客户,我们可以为他们设置专门独立的服务实例,或是服务集群与其他客户隔离开来,对于一些比较小的用户来说,可以让他们共享一个服务实例,这样可以节省相关的资源。

对于“多租户”的架构来说,会引入一些系统设计的复杂度。一方面,如果完全隔离,资源使用上会比较浪费,如果共享,又会导致程序设计的一些复杂度。

通常来说多租户的做法有三种。

  1. 完全独立的设计。每个租户有自己完全独立的服务和数据。
  2. 独立的数据分区,共享的服务。多租户的服务是共享的,但数据是分开隔离的。
  3. 共享的服务,共享的数据分区。每个租户的数据和服务都是共享的。

一般来说,技术方案会使用折衷方案,也就是中间方案,服务是共享的,数据通过分区来隔离,而对于一些比较重要的租户(需要好的隔离性),则使用完全独立的方式。

隔离设计的重点

要能做好隔离设计,我们需要有如下的一些设计考量。

  1. 我们需要定义好隔离业务的大小和粒度,过大和过小都不好。这需要认真地做业务上的需求和系统分析。
  2. 无论是做系统版块还是多租户的隔离,你都需要考虑系统的复杂度、成本、性能、资源使用的问题,找到一个合适的均衡方案,或是分布实施的方案尤其重要,这其中需要你定义好要什么和不要什么。因为,我们不可能做出一个什么都能满足的系统。
  3. 隔离模式需要配置一些高可用、重试、异步、消息中间件,流控、熔断等设计模式的方式配套使用。
  4. 不要忘记了分布式系统中的运维的复杂度的提升,要能驾驭得好的话,还需要很多自动化运维的工具,尤其是使用像容器或是虚拟机这样的虚拟化技术可以帮助我们更方便地管理,和对比资源更好地利用。否则做出来了也管理不好。
  5. 最后,你需要一个非常完整的能够看得到所有服务的监控系统,这点非常重要。

个人思考:故障隔离其实就是要保证在发生故障的时候,要做到影响最小。第一种按照服务隔离,目前大部分公司都是采用微服务架构,也就天然满足了按照服务隔离。至于按照用户隔离。我理解在数据量不大的时候,不用采用这种,毕竟开发成本比较大。而一旦数据量很大的时候,我们可以采用共享服务,然后数据独立分区这种,做数据分片,减轻DB压力。

经验分享 程序员 微信小程序 职场和发展