专栏文章
专栏文章
分布式系统系列
1. 分布式系统 #01:分布式一致性 2. 分布式系统 #02:分布式事务 3. 分布式系统 #03:分布式协调与选举 4. 分布式系统 #04:分布式系统设计模式 5. 分布式系统 #05:金融级分布式系统实践

分布式系统 #01:分布式一致性

发布于 2026-05-28 14:04 👁 15 次阅读
#分布式#consistency

本文系统梳理分布式一致性的核心理论与协议:从 CAP/BASE 的设计哲学,到强/顺序/因果/最终四种一致性模型,再到 Paxos、Raft、Gossip、向量时钟等具体实现方案。读完能清楚知道在什么场景下选哪种一致性保证,以及各协议的工作原理与取舍。

相关文章分布式事务 · 分布式协调与选举 · 分布式系统设计模式 · 金融级分布式系统实践


目录

章节 说明
CAP 定理 三角权衡,分布式系统的 PH 试纸
BASE 理论 CAP 中 AP 的延伸,追求可用性
一致性模型 强/顺序/因果/最终一致性对比
Paxos 协议 Basic Paxos 两阶段 + Multi-Paxos
Raft 协议 Leader 选举 + 日志复制 + 成员变更
Gossip 协议 最终一致性的传播机制
向量时钟 因果关系的逻辑时序工具

CAP 定理

CAP 是分布式系统的 PH 试纸,帮助我们在一致性和可用性之间做出有依据的权衡。

consistency cap theorem

三个指标

指标 含义 强调
C(Consistency) 每次读操作,要么读到最新写入的数据,要么返回失败 数据正确
A(Availability) 每次请求都能得到响应,但不保证是最新数据 服务可用
P(Partition Tolerance) 节点间出现消息丢失或高延迟时,系统仍能继续工作 容错能力

CAP 不可能三角

三个指标不可兼得,只能三选二。由于节点间的分区故障是分布式系统的必然现象,P 是必须保证的前提,因此实践中只剩 C 和 A 的取舍:

模式 含义 典型系统
CP 牺牲可用性,保证强一致性 etcd、Consul、HBase、ZooKeeper
AP 牺牲强一致性,保证高可用 Cassandra、DynamoDB、Eureka
CA 不存在于分布式系统(等同于单机) 单机 MySQL

常见误解:并非任何情况下都只能 C 和 A 选一个。在没有发生网络分区时(系统绝大多数时候的状态),C 和 A 可以同时保证。只有在网络分区发生时才需要二选一。

实践案例:InfluxDB 的 CAP 设计


BASE 理论

BASE 是 CAP 中 AP 的延伸,是对大规模互联网分布式系统实践的总结。核心思想:优先保证可用性,允许数据在一段时间内不一致,但最终达到一致

三个核心概念

概念 含义
Basically Available(基本可用) 出现故障时,允许损失部分功能的可用性,保障核心功能可用
Soft State(软状态) 允许系统存在中间状态(不同节点数据副本短暂不一致),不影响整体可用性
Eventually Consistent(最终一致性) 系统中所有数据副本经过一段时间同步后,最终能达到一致状态

实现基本可用的四板斧

  1. 流量削峰:错开不同区域的访问请求(如 12306 按区域分时段售票)
  2. 延迟响应:请求排队处理,牺牲响应时间保核心功能
  3. 体验降级:用低质量替代高质量(如用小图替代原图)
  4. 过载保护:超时请求直接拒绝,队列满后清除排队请求

实现最终一致性的三种方式

方式 原理 性能消耗 推荐度
写时修复 写入时检测不一致并修复,无需对比 优先选择
读时修复 读取时检测不一致并修复(如 Cassandra Read Repair) 次选
异步修复 定时对账检测副本差异(反熵) 补充手段

ACID vs BASE:ACID 追求强一致性,适合金融等强事务场景;BASE 追求最终一致性,适合大规模互联网分布式系统。两者都保证持久性,是正确性与性能之间的不同权衡。


一致性模型

一致性模型是正确性与性能之间的权衡,强度越高实现成本越大。

consistency levels

四种经典模型(从强到弱)

模型 定义 特征
线性一致性(强一致性) 写操作完成后,所有客户端立即能读到最新值;所有客户端看到的顺序符合时间先后 有全局时间顺序,最严格
顺序一致性 所有进程看到的操作顺序一致,但不要求符合真实时间顺序 有 total order,放松了时间约束
因果一致性 有因果关系的操作顺序在所有节点一致,无因果关系的并发操作可以不同顺序 只保证因果有序,无 total order
最终一致性 所有副本在经过一段时间后最终达到一致,过程中可读到任意旧值 最宽松,性能最高
强度:线性一致性 > 顺序一致性 > 因果一致性 > 最终一致性
性能:线性一致性 < 顺序一致性 < 因果一致性 < 最终一致性

以用户为中心的一致性

模型 含义 场景
单调读一致性 读到新值后,不会再读到比它旧的值 防止数据"回退"
单调写一致性 同一进程的写操作按顺序完成 顺序写入场景
写后读一致性 写入后,该进程的后续读一定能读到写入的值 主从读写分离时写主读主
读后写一致性 读到某值后的写操作,基于不低于该值的版本 防止基于过期数据写入

Paxos 协议

Paxos 是分布式共识的奠基性算法,过去几十年里是分布式共识的代名词。

Basic Paxos

目标:多个节点就单个值达成共识。

三种角色

角色 职责
Proposer(提议者) 接收客户端请求,发起二阶段提交,协调共识
Acceptor(接受者) 对提议的值进行投票,存储接受的值
Learner(学习者) 被动接受达成共识的值,不参与投票(数据备份节点)

两阶段流程

sequenceDiagram
    participant P as Proposer
    participant A1 as Acceptor-1
    participant A2 as Acceptor-2
    participant A3 as Acceptor-3
    Note over P,A3: 阶段一:Prepare(准备)
    P->>A1: Prepare(n=5)
    P->>A2: Prepare(n=5)
    P->>A3: Prepare(n=5)
    A1-->>P: Promise(尚无提案)
    A2-->>P: Promise(尚无提案)
    A3-->>P: Promise(尚无提案)
    Note over P,A3: 阶段二:Accept(接受)
    P->>A1: Accept[5, value=7]
    P->>A2: Accept[5, value=7]
    P->>A3: Accept[5, value=7]
    A1-->>P: Accepted
    A2-->>P: Accepted
    A3-->>P: Accepted
    Note over P,A3: 达成共识:value=7

Acceptor 的三个承诺

  1. 若 Prepare 请求的提案编号 ≤ 已响应的最大编号,不响应该 Prepare
  2. 若 Accept 请求的提案编号 < 已响应的最大编号,不通过该提案
  3. 若之前有通过提案,在 Prepare 响应中包含已通过的最大编号提案信息

容错能力:少于一半的节点故障时,共识协商仍正常工作("大多数"原则)。

Multi-Paxos

目标:就一系列值达成共识(Basic Paxos 只能处理单个值)。

Basic Paxos 的两个痛点

  1. 多个 Proposer 同时提案会导致提案冲突,需要重新协商
  2. 每次都需要 2 轮 RPC(Prepare + Accept),延迟高

Multi-Paxos 的两个改进

改进 方式 效果
引入 Leader 唯一 Proposer,消除提案冲突 无竞争,稳定
省略 Prepare 阶段 Leader 稳定时直接进入 Accept 阶段 减少一半消息往返

重要:兰伯特的 Multi-Paxos 是思想而非完整算法,缺少选举 Leader 等实现细节。Chubby、Raft 等都是基于 Multi-Paxos 思想的具体实现。Multi-Paxos 的正确性未经严格证明,生产环境优先选择 Raft


Raft 协议

Raft 是当前分布式系统开发的首选共识算法,以"一切以 Leader 为准"的方式实现共识,在可理解性上远优于 Paxos。

三种节点状态

flowchart LR
    F[Follower<br/>跟随者] -->|超时未收到心跳| C[Candidate<br/>候选人]
    C -->|获得多数票| L[Leader<br/>领导者]
    C -->|发现更高任期| F
    L -->|发现更高任期| F
    style L fill:#cfc,stroke:#060
    style C fill:#ffc,stroke:#660
    style F fill:#eef,stroke:#66c

Leader 选举

流程

  1. 初始所有节点为 Follower
  2. Follower 等待心跳超时(随机超时时间,150~300ms),转为 Candidate
  3. Candidate 自增任期编号,给自己投票,向其他节点发送 RequestVote RPC
  4. 获得大多数选票的 Candidate 成为 Leader,开始发送心跳

选举规则

任期(Term):单调递增的整数,用于检测过期信息。发现自己任期编号比其他节点小,立即降为 Follower。

日志复制

日志项结构[索引值, 任期编号, 指令]

sequenceDiagram
    participant C as Client
    participant L as Leader
    participant F1 as Follower-1
    participant F2 as Follower-2
    C->>L: 写请求(SET x=3)
    L->>L: 追加日志项
    L->>F1: AppendEntries RPC
    L->>F2: AppendEntries RPC
    F1-->>L: 复制成功
    F2-->>L: 复制成功
    Note over L: 大多数节点确认,提交日志
    L->>L: 应用到状态机
    L-->>C: 返回成功
    Note over F1,F2: 下次心跳时,<br/>Follower 得知提交位置,<br/>应用到自己的状态机

日志一致性修复:Leader 通过一致性检查找到与 Follower 相同日志的最大索引,然后强制覆盖之后的不一致日志项。Leader 从不覆盖自己的日志。

成员变更

直接从旧配置切换到新配置可能导致同一任期出现两个 Leader(脑裂)。Raft 通过**联合共识(Joint Consensus)**解决:先进入同时使用新旧两个配置的过渡状态,再切换到新配置。

Raft vs Paxos 对比

维度 Raft Multi-Paxos
可理解性 高,限制多(日志必须连续) 低,灵活但复杂
日志要求 必须连续 不要求连续
Leader 选举 明确定义 未定义,需自行实现
正确性证明 已证明 未完整证明
生产应用 etcd、Consul、CockroachDB Chubby、Spanner(早期)

Gossip 协议

Gossip(流言蜚语)协议通过随机、传染性的方式将信息传播到整个网络,实现最终一致性。适合极端情况下(如集群只剩一个节点)也需要运行的系统。

三板斧

方式 原理 特点
直接邮寄(Direct Mail) 直接发送更新数据,失败时缓存重传 实时性高,但可能因缓存满而丢数据,单独使用无法保证最终一致性
反熵(Anti-entropy) 节点定期随机选择另一节点,互相交换所有数据消除差异 可靠,但通信成本高(节点两两对比),适合节点数量固定的系统
谣言传播(Rumor mongering) 有新数据的节点变为活跃状态,周期性向其他节点扩散,直到所有节点都有该数据 传染性强,适合动态变化的分布式系统

反熵的三种实现方式

sequenceDiagram
    participant A as 节点A
    participant B as 节点B
    Note over A,B: 推方式(Push)
    A->>B: 发送自己的全部副本数据
    Note over B: 修复自己的熵
    Note over A,B: 拉方式(Pull)
    A->>B: 请求对方的全部副本数据
    B-->>A: 返回数据
    Note over A: 修复自己的熵
    Note over A,B: 推拉方式(Push-Pull)
    A->>B: 互相交换数据
    B-->>A: 互相交换数据
    Note over A,B: 双方都修复熵

实践建议:直接邮寄必须实现(低开销);节点固定时用反熵;节点动态变化时用谣言传播。反熵建议引入校验和(Checksum)降低数据对比量,并做成可配置开关。


向量时钟

向量时钟(Vector Clock)是一种用于追踪分布式系统中事件因果关系的逻辑时钟,解决"哪个事件先发生"的问题。

核心思想

每个节点维护一个向量 [t1, t2, ..., tn],其中 ti 表示节点 i 的本地逻辑时间。

更新规则

因果关系判断

与物理时钟的对比

维度 物理时钟 向量时钟
同步要求 需要全局时钟同步 不需要
因果判断 不可靠(时钟漂移) 精确
开销 O(n),n 为节点数
典型应用 日志时间戳 Dynamo、Riak 冲突检测

应用场景:Dynamo 使用向量时钟检测多副本数据冲突,当检测到并发写入时,将冲突数据交给应用层(或客户端)解决。


参考资料

← 返回列表

评论 (0)

暂无评论,来留下第一条吧。

发表评论