Skip to content

第八章:分布式系统的麻烦

1. 分布式系统的基本现实

分布式系统最难的问题不是“机器会不会坏”,而是“只坏一部分”。部分失败导致状态不确定,系统必须在不完美信息下做决策。

2. 不可靠网络

2.1 请求失败的不可判定性

请求超时后,发送方通常无法区分:

  • 请求未送达。
  • 对端已处理但响应丢失。
  • 对端正在处理但尚未返回。

因此超时语义应设计为“未知结果”,并配合幂等重试。

2.2 超时配置原则

超时过短会误判故障并引发级联切换,超时过长会拖慢恢复。实践中应按延迟分布动态调整,而非固定常量。

2.3 同步网络假设的局限

互联网与数据中心网络基于分组交换,延迟受排队、拥塞与调度影响,通常无法给出严格上界。

3. 不可靠时钟

3.1 两类时钟

  • 墙上时钟:表示日历时间,可能跳变或回拨。
  • 单调时钟:只用于测量时长,不用于跨节点时间比较。

3.2 时钟同步误差

即使使用 NTP,时钟仍有漂移与同步误差。把物理时间戳直接当作全局真相,容易导致顺序错误与数据覆盖。

3.3 依赖时钟的风险

LWW 等策略若仅基于物理时钟,会在时钟漂移时丢失逻辑上更新的数据。涉及顺序语义时,更可靠做法是逻辑时钟或共识序号。

3.4 TrueTime 思路

SpannerTrueTime 通过返回时间区间而非单点时间,显式建模不确定性,再通过提交等待换取外部一致性。

4. 进程暂停与僵尸节点

4.1 进程暂停来源

GC、页故障、虚拟化抢占、系统调度都可能让进程暂停数百毫秒到数秒。

4.2 领导者租约风险

进程暂停期间租约可能已过期,恢复后若继续写入会造成“僵尸写”。必须依赖外部校验而非进程自信。

4.3 防护令牌(Fencing Token)

每次获取锁都分配单调递增令牌,下游存储拒绝旧令牌写入。该机制是避免僵尸节点破坏数据的关键。

5. 真相、谎言与系统模型

5.1 真相由多数派定义

在分布式系统里,单节点自我认知不可靠,多数派(quorum)决定系统事实。

5.2 拜占庭故障边界

多数业务系统采用“崩溃故障模型”,不处理恶意节点。若处于强对抗环境(区块链、高安全系统),才需要拜占庭容错模型。

5.3 常用系统模型

  • 时间模型:同步、异步、部分同步。
  • 故障模型:崩溃停止、崩溃恢复。

现实系统通常按“部分同步 + 崩溃恢复”建模。

5.4 正确性定义

  • 安全性(Safety):坏事不会发生。
  • 活性(Liveness):好事最终发生。

设计分布式协议时,应先保证安全性,再优化活性与性能。

6. 实务建议

  • 把“未知”作为一等状态建模,不要把超时等价为失败。
  • 所有跨节点写入操作都应有幂等键或去重语义。
  • 锁与主选举必须配套 fencing,避免僵尸写。