目录
正在加载目录…
专栏文章
专栏文章
分布式系统系列
1. 分布式一致性 2. 分布式事务 3. 分布式协调与选举 4. 分布式系统设计模式 5. 金融级分布式系统实践

分布式一致性

发布于 2026-05-28 14:04 · 最后编辑于 2026-07-31 15:55 · 字数 4,193 👁 80 次阅读

本文系统梳理分布式一致性的核心理论与协议:从 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 设计

  • META 节点(存储数据库名、表名等关键元信息)→ 选 CP,采用 Raft 强一致性。元信息不一致会导致写入失败,代价极高。
  • DATA 节点(存储时序数据)→ 选 AP,采用分片 + 多副本。时序数据追求高并发写入和水平扩展,允许短暂不一致。

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,开始发送心跳

选举规则

  • 每个任期每个节点只能投一票(先来先服务)
  • 日志完整性高的节点(最后一条日志项任期编号更大,或索引更大)才能当选 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 对比

维度RaftMulti-Paxos
可理解性高,限制多(日志必须连续)低,灵活但复杂
日志要求必须连续不要求连续
Leader 选举明确定义未定义,需自行实现
正确性证明已证明未完整证明
生产应用etcd、Consul、CockroachDBChubby、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 的本地逻辑时间。

更新规则

  • 节点执行本地事件:自增自己的计数器
  • 节点发送消息:附带当前向量时钟
  • 节点接收消息:取每个分量的最大值,再自增自己的计数器

因果关系判断

  • 事件 A 的向量时钟在每个分量上都 ≤ 事件 B → A 发生在 B 之前(A → B)
  • 两个事件互不支配 → 并发事件,无因果关系

与物理时钟的对比

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

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

参考资料

← 返回列表

评论 (0)

暂无评论,来留下第一条吧。
登录注册 后才能发表评论