---
title: 故障模型
url: https://doc.liz6.com/distributed-systems/01-basic-theory/03-fault-models
locale: zh
area: distributed-systems
tags:
- distributed-systems
- 基础理论
date: 2026-06-30
modified: 2026-06-30
description: 节点可能崩溃、可能失联、可能撒谎。从 crash-stop 到 Byzantine,故障模型的每一次升级都让协议设计难度翻倍——而工程中"超时多长算故障"本身就是一个没有正确答案的权衡:太短误判活节点,太长系统空等。
---

# 故障模型

> 节点可能崩溃、可能失联、可能撒谎。从 crash-stop 到 Byzantine,故障模型的每一次升级都让协议设计难度翻倍——而工程中"超时多长算故障"本身就是一个没有正确答案的权衡:太短误判活节点,太长系统空等。

## 故障分类

### Crash-Stop (Fail-Stop)

节点停止执行后**不再重启**。这是最简单的故障模型——一旦节点 crash，它就永远不产生新的输出。共识协议（Paxos/Raft）在这个模型下有简洁的证明。

特点：不需要持久化（crash 后节点不需要恢复 log），状态可以放在内存。但实践中极少数系统是真正的 crash-stop——大多数系统需要 crash-recovery。

### Crash-Recovery

节点停止，但经过一段（任意）时间后**重启并恢复执行**。恢复需要从持久存储（WAL/journal）重放 pre-crash 状态。这是最实际的故障模型——Raft/etcd 就是针对 crash-recovery 设计的。

恢复后的关键问题：重启的节点必须能**证明**它的 log 没有丢失——即 log 被持久写入并在 crash 前确认了。这就是 Raft 为什么要求 `fsync` 日志条目后才回复 leader。

### Byzantine (拜占庭) 故障

节点可以**任意行为**——包括发送伪造消息、选择性响应、蓄意破坏。不仅是恶意攻击：内存 bit-flip (宇宙射线)、固件 bug、网络设备错误转发都可能产生 Byzantine 行为。

Byzantine 比 crash 难得多：Paxos/Raft 只容忍 `f` 个 crash 就需要 `2f+1` 个节点；PBFT（Practical Byzantine Fault Tolerance）需要 `3f+1` 个节点来容忍 `f` 个 Byzantine 节点。

原因：Byzantine 节点可以**对不同的诚实节点说不同的话**——诚实节点无法区分"对方在撒谎"和"网络丢包"。PBFT 的 3f+1 的下限已被证明是必要的。

### 实践中的分布

实际系统极少需要 Byzantine 容错——在一个封闭的数据中心/集群中，crash-recovery 覆盖了绝大多数故障。Byzantine 主要出现在：

- 区块链/加密货币（节点互不信任）
- 跨组织协作（没有共同信任根）
- 极其关键的基础设施（Spanner 用 TrueTime 防止了某些 Byzantine 式时钟攻击）

## 网络分区

分区不等于 crash——节点仍在运行，能接受客户端请求，但不能与其他节点通信。分区是对 CAP 定理的核心威胁：**分区发生时，你必须选择一致或可用。**

### 对称分区 vs 非对称分区

- 对称分区：集群被等分为两部分，每部分都有节点的多数 → (用 Raft) 只有有 majority 的那一半能选举 leader 并继续服务
- 非对称分区：单个节点与其他所有节点断连 → 它不能成为 leader，也不会造成脑裂

### Split-Brain (脑裂)

多 leader 系统 + 分区 = 两个分区各自选举了 leader → 两边同时接受写入 → 分区恢复时冲突。经典的解决方案：

- Raft/Paxos: 永远只有 majority partition 能有 leader（数学保证）
- 系统级防御：STONITH (Shoot The Other Node In The Head) → fence 旧 master 甚至直接断电

## 超时

分布式系统的核心张力：**超时太短 = 误判 crash (false positive)；超时太长 = 故障检测慢 (增加不可用窗口)**。

Raft 的选举超时就是典型：150-300ms 随机化，既保证不同 candidate 有不同的超时（避免 split vote），又要足够长以覆盖正常的 RPC 延迟。

### 为什么没有"正确"的超时

网络延迟不是高斯分布——它有长尾（tail latency）。即使 p99 延迟是 10ms，p99.9 可能就跳到 100ms。如果你设 timeout=100ms，0.1% 的请求会误判为超时。如果设 timeout=1s，故障检测延迟就是 1s——这段期间系统不可用。

这个问题没有理论解，只有工程权衡。在实践中：用 `φ-accrual failure detector`（见 05 章）输出 suspicion level 而不是二值判断——让应用层决定"多大的怀疑值得做 failover"。

## 参考

- **论文**: "Impossibility of Distributed Consensus with One Faulty Process" (FLP, 1985)
- **论文**: "Practical Byzantine Fault Tolerance" (Castro & Liskov, 1999)
- **论文**: "The φ Accrual Failure Detector" (Hayashibara et al, 2004)

*Keywords: crash-stop, crash-recovery, Byzantine fault, network partition, split-brain, FLP, timeout, φ-accrual*
