分布式系统的设计

分布式系统应该具有的架构特性(设计方向):高并发、可扩展性、高可用性、高性能。同时分布式系统中存在的一致性问题,也需要有对应的解决方案。

高并发并不是一种技术,而是系统要面临的技术技术场景。在这个场景下,确保高并发时的用户体验,系统不应该出现错误且以极快的速度给用户响应。可用性、可扩展性、高性能就是用于定量分析高并发系统的3个视角。

分布式系统的高可用性

目标是为了让系统尽可能不发生错误,或者发生错误后的损失降到最低。系统运行时间是定量,不可用时间是变量。

发布/故障/压力/外部依赖导致可用性问题

变化数量*变化产生故障的比例*故障的影响*故障持续的时间

初始设计按照20/10/5来分别设计、开发、发布,这里说的数字是实际流量的倍数。

容错设计,单点故障、特性开关、服务分级、降级设计、超时重试

隔离策略:进程、用户、集群、租户、物理、逻辑

熔断:失败时候主动切断避免灾难发生

流控:流控算法/流控策略(在什么地方做流控)

容量预估:全链路压测明白系统的当前能力现状,而不是单接口、单业务,生产环境直接压;

故障演练:故障模式梳理以及实践验证容灾方案

数据迁移:逻辑分离/物理分离

分布式系统的高性能

目标是为了让尽可能多的用户,用尽可能少的时间得到系统的响应。任务目标是定量,任务完成耗时是变量。

内存IO时间+网络IO时间+CPU时间+磁盘IP时间+等待时间1

响应时间/吞吐量/负载敏感度/可伸缩性

附在敏感度为系统响应是随时间变化的程度,需要可量化。用户请求过多的时候,系统响应时间是如何的一个衰减速度。

可伸缩性为系统扩容增加资源对于性能的影响,可量化衡量,即吞吐量扩1倍,需要多少服务资源的衡量;

分布式系统的可扩展性

目标是为了支撑可用性和高性能,在一些特殊情况下,不得不对系统系统进行调整时,能够以低成本的方式完成的能力。

AKF扩展立方体

可以沿着X/Y/Z轴三个方向进行扩展。

X轴扩展也叫水平扩展/横向扩展,通过复制实例(往往无状态),前端对流量进行负载均衡,分摊整体压力为目的进行扩展。

Y轴扩展依据服务或者资源扩展,依据服务拆分,各个微服务依据当前能力独立进行横向扩展,降低当前系统的复杂度

Z轴扩展依据当前的业务查询或计算结果进行拆分,即分片的思想。基于分区扩展,扩展性更强,突破单张表的数据规模上限,但是对于数据迁移复杂;

数据库的X/Y/Z轴扩展:主从复制、分库/分表、分片sharding

分布式系统的一致性设计

事务:原子性、一致性、隔离性、持久性

CAP定理:一致性/可用性/分区容错性,三选二

BASE理论:强一致性、弱一致性、最终一致性;依据业务的考量来决策,不一致性场景下时候是基本可用、不可用、可接受;

Quorum机制:强一致性的保障在写入数据的时候,所有节点成功后才算成功,此时写性能较差;转变思路为在读的阶段再决策,确保每次均能读到最新的数据。Quorum机制满足公式:备份个数N<成功写入W个+读取R个备份

租约机制Lease:为了实现一致性,确保节点中有一个leader,leader负责数据写入、follower负责数据读取,管理节点M通过心跳判断各个节点,指定Leader,Leader故障后重新选取Leader。

脑裂:Paxos、Raft、Lease算法确保

分布式系统最终体现在数据的一致性(严格一致性、顺序一致性、因果一致性):

X轴扩展数据可以是多个副本,多个副本不同的物理存储,故障时可以访问正常的副本数据;需要解决数据写入性能问题

Z轴扩展对数据进行分区,即Sharding;

分布式系统的用户(泛化)一致性模型(需要有标识,且唯一):

单调读一致性,单调写一致性、写后读一致性、读后写一致性

弱一致性:写入一个数据成功后,在数据副本上可能读出来,也可能读不出来,不保证每个副本的数据一定一致;

最终一致性:写入一个数据后,在其他副本有可能读不到最新值,单在某个时间窗口之后保证能最终读到;(重试机制、本地日志复制如binglog、可靠事件模式、Saga事务模型,TCC事务模型)

强一致性:数据一旦写入成功,任何副本上在写入后的任意时刻都能读到最新值;实现模型:两阶段提交/三阶段提交

分布式系统中的八大谬误

  • 网络是可靠的

    实际不是可靠的,应用系统中需要做的事情可能有:retry,acknowledge import messages, identify/ignore duplicates, record messages, verifiy message integrity。

  • 传输是无延迟

    延迟指数据从一个地方传递到另一个地方需要的时间,这中间带宽决定了同时可以传输多少数据。

  • 带宽是无限的

    其实不是,随着带宽的增长,我们传输的数据量也在增加,同时传输就存在丢包的问题。在信息的传递和延迟之间是要trade-off。

  • 网络是安全的

    通往网络的安全是多层的,包括基础设施、网络传输和应用层等;

  • 拓扑是不变的

    系统中不应该依赖特定的路由或节点,需要同时提供位置透明性和发现服务

  • 传输是无成本的

    我们从应用层到传输层的数据传递,需要对数据进行编码,这需要消耗时间和计算资源。而设置和运行网络都是需要代价,需要金钱购买。

  • 网络是同构的

    不应该在应用层去依赖一些自营的协议,而是通用的协议。

  • 只有一个管理员

    当没有出现问题的时候,我们不需要管理员。但是一旦问题发生,就会抓狂的需要。

REF


  1. Latency Numbers Every Programmer Should Know (github.com) ↩︎

Liao lile
Liao lile
架构师 | 系统工程师

目前主要方向在微服务、服务网格等云原生相关领域技术