33. 分布式系统基础

建立分布式系统的完整心智模型:为什么必须分布、故障模型与部分失效、CAP 定理的正确理解与 PACELC 补充、线性一致性与因果一致性等一致性谱系、主从与去中心复制策略、Raft 共识算法的选举与日志复制流程、逻辑时钟与全序广播,以及幂等、重试、熔断等工程实践。

1. 为什么需要分布式系统

1.1 三类驱动力

  1. 可扩展性(Scalability):单机 CPU、内存、磁盘都有物理上限,纵向扩展(Scale Up)成本呈指数上升,横向扩展(Scale Out)更经济。
  2. 高可用(Availability):单机总有故障概率,多副本冗余才能把整体可用性从 99% 提到 99.99%。
  3. 地理分布(Latency):用户遍布全球时,把数据放到离用户近的地方才能降低延迟。

1.2 分布式系统的代价

分布式不是免费的午餐,它引入了单机系统根本不存在的复杂性:

  • 部分失效:一部分节点挂了,其他节点还在跑,系统处于「既不成功也不失败」的中间态。
  • 网络不可靠:消息可能丢失、重复、乱序、延迟任意长。
  • 无全局时钟:各节点时钟有偏差,无法简单比较事件先后。
  • 并发与一致性:多副本并发写入会产生冲突,需额外机制收敛。

一句话概括:分布式系统的核心难点是「如何在不可靠的组件之上,构建对上层表现为可靠的整体」。

2. 基本模型与故障模型

2.1 两类故障

类型表现处理难度
崩溃故障 Crash节点停止响应,不再发消息相对可控
拜占庭故障 Byzantine节点可能发送错误甚至恶意消息极难,需 BFT 共识

绝大多数工程系统假设崩溃-恢复(Crash-Recovery)模型:节点可能崩溃,但重启后不撒谎(可能丢内存状态,磁盘数据保留)。区块链场景才需要拜占庭容错。

2.2 同步 vs 异步

  • 同步模型:消息延迟有上界,可用超时判定节点死亡。
  • 异步模型:延迟无上界,无法区分「节点慢」与「节点死」——这是 FLP 不可能定理的根源。
  • 部分同步模型:现实中常用的折中,大部分时间同步,偶尔异步。

FLP 不可能定理:在完全异步、允许一个节点崩溃的系统中,不存在既保证安全性又保证活性的确定性共识算法。工程上靠随机化或超时绕开。

3. CAP 定理

3.1 三个字母的含义

  • C(Consistency)一致性:所有节点读到同一份最新数据,等价于线性一致性。
  • A(Availability)可用性:每个请求都能在有限时间内得到非错误响应。
  • P(Partition tolerance)分区容忍:网络分区时系统继续工作。

3.2 正确理解

CAP 不是说「三选二」,而是:当分区发生时,只能在 C 与 A 之间二选一。 网络分区是客观事实,P 无法放弃,所以真正的抉择是 CP 还是 AP。

网络正常时:  C 与 A 可同时满足
网络分区时:  ┌── 选 C(拒绝服务,保一致)→ CP,如 ZooKeeper、etcd
            └── 选 A(继续服务,容忍不一致)→ AP,如 Cassandra、Dynamo

3.3 PACELC 补充

CAP 只描述了分区期间的行为,PACELC 补上了正常时的权衡:

if Partition:  在 A 与 C 之间选
Else:          在 Latency 与 C 之间选

即:即使没有分区,多副本同步复制也会带来延迟,系统仍要在「低延迟」与「强一致」之间取舍。

4. 一致性模型

4.1 一致性谱系

模型含义典型系统
线性一致 Linearizable表现为单一副本,读写实时有序etcd、Spanner
顺序一致 Sequential所有节点看到同一顺序,但不要求实时部分内存模型
因果一致 Causal有因果关系的操作保持顺序,并发可乱序COPS、部分 KV
读己之写 Read-Your-Writes用户能读到自己的更新会话一致性方案
最终一致 Eventual停止写入后最终收敛DNS、Cassandra

4.2 线性一致性的价值

线性一致让分布式系统看起来像一台单机,是最容易推理的模型,但代价是延迟高(需跨节点协调)。ZooKeeper、etcd 这类协调服务必须提供线性一致(至少写线性化)。

4.3 会话保证

工程上常用一组折中保证替代完整强一致:

  • 单调读:读到的版本不会倒退。
  • 读己之写:读自己刚写的值。
  • 单调写:同一客户端的写按序应用。

这些保证足以满足大多数业务,且无需全局协调。

5. 复制策略

5.1 主从复制 Leader-Follower

写请求 → Leader ──复制日志──▶ Follower1
                     └──────▶ Follower2
读请求 → 可路由到任意副本(取决于一致性要求)
  • 优点:写入顺序由 Leader 单点确定,无写冲突;实现简单。
  • 缺点:Leader 是瓶颈与单点(需选举恢复);故障切换期间可能不可用。

5.2 同步 vs 异步复制

方式一致性延迟数据丢失风险
同步强高(等最慢副本)无
半同步中中(等一个副本)低
异步最终低Leader 挂会丢未复制数据

MySQL 半同步、Kafka acks=all 都是这一谱系的具体实现。

5.3 去中心复制模型

客户端可写任意节点,节点间通过 Gossip 传播,冲突用 向量时钟检测、用 CRDT / LWW 合并。DynamoDB、Cassandra 属此类,可用性高但只提供最终一致。

6. 共识算法

6.1 共识要解决什么

多个节点就同一个值(或同一串操作日志顺序)达成一致,且满足:

  • 一致性(Agreement):所有正确节点决定相同值。
  • 有效性(Validity):决定的值必须是某个节点提议过的。
  • 终止性(Termination):最终都能做出决定。

6.2 Raft 核心流程

Raft 把共识拆成领导者选举 + 日志复制 + 安全性三块,比 Paxos 更易理解:

角色: Leader / Follower / Candidate
任期: 逻辑时钟,单调递增,用于识别过期消息

选举:
① Follower 超时未收到心跳 → 变 Candidate,任期 +1
② 向所有节点拉票,先到先得
③ 获得多数派(N/2 + 1)票 → 成为 Leader
④ 开始周期性发送心跳维持权威

日志复制:
① 客户端请求 → Leader 追加到本地日志(未提交)
② 并行发送 AppendEntries 给所有 Follower
③ 多数派确认后 → 提交该条目,应用到状态机
④ 通知 Follower 提交

多数派(Quorum)是关键:任意两个多数派必有交集,保证新 Leader 一定包含已提交的日志,从而不会丢失已确认的写。

6.3 选举超时的随机化

若所有 Follower 同时超时,会平分选票导致活锁。Raft 给每个节点随机化选举超时(如 150~300ms),使通常只有一个节点先发起选举,快速收敛。

7. 时间、时钟与顺序

7.1 物理时钟不可靠

NTP 同步后仍有毫秒级偏差,且可能回拨。不能用物理时间戳判定事件的因果顺序。

7.2 逻辑时钟

  • Lamport 时钟:每个事件递增计数器,消息携带时间戳,接收方取 max(本地, 收到) + 1。给出偏序:a → b 则 L(a) < L(b),反之不成立。
  • 向量时钟:每节点维护一个向量,可判断并发与因果:若 V(a) < V(b) 则 a 先于 b;若互不包含则并发。代价是空间随节点数增长。
  • 混合逻辑时钟 HLC:物理时间 + 逻辑计数,兼顾近似实时与因果(CockroachDB 使用)。

7.3 全序广播

若所有节点对消息顺序达成一致(全序广播 Total Order Broadcast),则等价于共识。Raft 的日志复制本质上就是全序广播。

8. 典型架构与工程实践

8.1 常见模式

  • 协调服务:etcd/ZooKeeper 提供选主、配置、分布式锁,基于共识算法。
  • 分片 + 复制:数据按 key 分片(Sharding),每片多副本,兼顾扩展与容错。
  • 读写分离:写走 Leader,读走 Follower,需处理复制延迟导致的读到旧值。
  • 幂等设计:请求带唯一 ID,服务端去重,使重试安全。

8.2 工程清单

超时与重试: 指数退避 + 抖动,避免重试风暴
熔断降级:   下游故障时快速失败,保护自身
幂等键:     写操作携带 request_id 去重
一致性哈希: 节点增减时最小化数据迁移
健康检查:   区分存活(liveness)与就绪(readiness)

8.3 超时值的经验

超时不是拍脑袋定的:应基于P99 延迟设定,并小于上层超时,形成逐层收敛的超时预算(Timeout Budget),避免「重试放大」把下游打垮。

9. 常见陷阱

  • 把 CAP 理解为「三选二」:实际是分区时的 C/A 取舍,正常时还要考虑延迟。
  • 用物理时钟排序事件:时钟回拨会导致顺序错乱,需逻辑时钟或 HLC。
  • 认为重试总是安全:非幂等操作重试会造成重复扣款、重复下单。
  • 忽视脑裂:网络分区时两个 Leader 同时写,需多数派机制或 fencing token 防止。
  • 过度追求强一致:全局线性一致延迟高,多数业务用会话一致性即可。
  • 忘记处理复制延迟:读写分离后立即读可能读到旧值,需读己之写保证。
  • 无界重试:没有退避与上限的重试会放大故障,形成雪崩。

参考文章

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「计算机基础」更多文章

  1. 34. 编程范式与类型系统
  2. 32. 加密与安全基础
  3. 31. 虚拟内存与分页