第八章:分布式系统的麻烦
1. 分布式系统的基本现实
分布式系统最难的问题不是“机器会不会坏”,而是“只坏一部分”。部分失败导致状态不确定,系统必须在不完美信息下做决策。
2. 不可靠网络
2.1 请求失败的不可判定性
请求超时后,发送方通常无法区分:
- 请求未送达。
- 对端已处理但响应丢失。
- 对端正在处理但尚未返回。
因此超时语义应设计为“未知结果”,并配合幂等重试。
2.2 超时配置原则
超时过短会误判故障并引发级联切换,超时过长会拖慢恢复。实践中应按延迟分布动态调整,而非固定常量。
2.3 同步网络假设的局限
互联网与数据中心网络基于分组交换,延迟受排队、拥塞与调度影响,通常无法给出严格上界。
3. 不可靠时钟
3.1 两类时钟
- 墙上时钟:表示日历时间,可能跳变或回拨。
- 单调时钟:只用于测量时长,不用于跨节点时间比较。
3.2 时钟同步误差
即使使用 NTP,时钟仍有漂移与同步误差。把物理时间戳直接当作全局真相,容易导致顺序错误与数据覆盖。
3.3 依赖时钟的风险
LWW 等策略若仅基于物理时钟,会在时钟漂移时丢失逻辑上更新的数据。涉及顺序语义时,更可靠做法是逻辑时钟或共识序号。
3.4 TrueTime 思路
Spanner 的 TrueTime 通过返回时间区间而非单点时间,显式建模不确定性,再通过提交等待换取外部一致性。
4. 进程暂停与僵尸节点
4.1 进程暂停来源
GC、页故障、虚拟化抢占、系统调度都可能让进程暂停数百毫秒到数秒。
4.2 领导者租约风险
进程暂停期间租约可能已过期,恢复后若继续写入会造成“僵尸写”。必须依赖外部校验而非进程自信。
4.3 防护令牌(Fencing Token)
每次获取锁都分配单调递增令牌,下游存储拒绝旧令牌写入。该机制是避免僵尸节点破坏数据的关键。
5. 真相、谎言与系统模型
5.1 真相由多数派定义
在分布式系统里,单节点自我认知不可靠,多数派(quorum)决定系统事实。
5.2 拜占庭故障边界
多数业务系统采用“崩溃故障模型”,不处理恶意节点。若处于强对抗环境(区块链、高安全系统),才需要拜占庭容错模型。
5.3 常用系统模型
- 时间模型:同步、异步、部分同步。
- 故障模型:崩溃停止、崩溃恢复。
现实系统通常按“部分同步 + 崩溃恢复”建模。
5.4 正确性定义
- 安全性(Safety):坏事不会发生。
- 活性(Liveness):好事最终发生。
设计分布式协议时,应先保证安全性,再优化活性与性能。
6. 实务建议
- 把“未知”作为一等状态建模,不要把超时等价为失败。
- 所有跨节点写入操作都应有幂等键或去重语义。
- 锁与主选举必须配套
fencing,避免僵尸写。