09

一致性与共识

让多个节点达成一致

阅读量:4 · 预计 12 分钟读完

线性一致性全序广播PaxosRaft
关联层级:L7 应用抽象
阅读进度4%

第九章:一致性与共识

导读

一致性与共识是分布式系统中的核心问题。在多个节点组成的系统中,如何让所有节点就某个值或状态达成一致,是分布式系统设计的关键挑战。

本章将深入探讨各种一致性模型和共识算法,分析它们的原理和适用场景。我们将学习线性一致性、顺序一致性、因果一致性等概念,理解Paxos、Raft等共识算法的工作原理。

通过本章的学习,你将理解:

  • 各种一致性模型的区别
  • 共识问题的定义和挑战
  • Paxos和Raft算法的原理
  • 共识算法的应用场景
  • 一致性与性能的权衡

核心概念详解

9.1 一致性模型

一致性模型定义了客户端对系统行为的预期。不同的一致性模型提供不同程度的保证。

9.1.1 线性一致性(Linearizability)

线性一致性是最强的一致性模型,也称为原子一致性。

定义

  • 每个操作看起来像是在某个瞬间原子完成的
  • 如果操作A在操作B之前完成,那么所有节点都应该看到A在B之前

示例

客户端1: write(x, 1) at time 10
客户端2: read(x) at time 15 → 返回1
客户端3: read(x) at time 20 → 返回1

所有节点都应该看到write(x, 1)在time 10完成,之后的读取都应该返回1。

优势

  • 语义简单,易于理解
  • 行为与单节点系统相同

局限

  • 性能低,需要等待所有节点确认
  • 在网络分区时不可用

适用场景

  • 分布式锁
  • _leader_选举
  • 需要强一致性的场景

9.1.2 顺序一致性(Sequential Consistency)

顺序一致性保证所有操作按某种顺序执行,所有节点看到相同的顺序。

定义

  • 所有操作按某种顺序执行
  • 所有节点看到相同的操作顺序
  • 每个操作按程序顺序执行

与线性一致性的区别

  • 线性一致性要求操作按真实时间顺序执行
  • 顺序一致性只要求操作按某种顺序执行,不要求按真实时间

示例

客户端1: write(x, 1)
客户端2: write(x, 2)

顺序一致性保证所有节点看到的顺序要么是write(x, 1) → write(x, 2),要么是write(x, 2) → write(x, 1),但不要求按真实时间顺序。

优势

  • 比线性一致性弱,性能更好
  • 仍然易于理解

局限

  • 仍然需要全局协调
  • 性能不如弱一致性模型

9.1.3 因果一致性(Causal Consistency)

因果一致性保证有因果关系的事件按顺序被所有节点看到。

定义

  • 如果事件A导致事件B,所有节点都先看到A,再看到B
  • 没有因果关系的事件可以以任意顺序被看到

示例

客户端1: write(x, 1)
客户端2: read(x) → 1
客户端2: write(x, 2)

write(x, 1)导致read(x) → 1,read(x) → 1导致write(x, 2)。所有节点都应该看到write(x, 1) → write(x, 2)。

实现方式

  • 版本向量(Version Vector)
  • 因果图(Causal Graph)

优势

  • 比线性一致性和顺序一致性弱,性能更好
  • 保证因果关系

局限

  • 实现复杂
  • 需要跟踪因果关系

适用场景

  • 聊天系统
  • 评论系统
  • 需要保持因果关系的场景

9.1.4 最终一致性(Eventual Consistency)

最终一致性保证在没有新的写入的情况下,所有节点最终会达到一致状态。

定义

  • 如果不再更新数据,所有节点最终会返回相同的值
  • 不保证何时达到一致

优势

  • 性能高,可用性高
  • 实现简单

局限

  • 可能读取到旧数据
  • 不保证因果关系

适用场景

  • DNS系统
  • 内容分发网络
  • 可以接受短暂不一致的场景

9.2 共识问题

共识问题是指多个节点就某个值达成一致。

9.2.1 共识的定义

共识问题

  • 多个节点提出一个值
  • 所有节点就一个值达成一致
  • 一旦达成一致,这个值不可改变

共识的要求

  • 一致性:所有节点就同一个值达成一致
  • 有效性:如果所有节点提出同一个值,则共识结果就是这个值
  • 终止性:所有非故障节点最终会达成一致
  • 完整性:每个节点最多决定一次

9.2.2 FLP不可能定理

FLP不可能定理

  • 在异步系统中,如果存在一个节点可能崩溃,则不存在确定性的共识算法
  • 这意味着在分布式系统中,共识问题无法完全解决

含义

  • 共识算法必须做出某种假设
  • 要么假设网络延迟有上限(部分同步)
  • 要么使用随机化算法
  • 要么假设可以检测节点故障

9.2.3 共识算法的应用

Leader选举

  • 多个节点选举一个Leader
  • Leader负责协调其他节点

分布式锁

  • 多个节点竞争一个锁
  • 只有一个节点可以获得锁

原子提交

  • 多个节点就事务的提交或回滚达成一致
  • 保证跨节点的事务一致性

状态机复制

  • 多个节点维护相同的状态
  • 所有节点执行相同的操作序列

9.3 Paxos算法

Paxos是最经典的共识算法,由Leslie Lamport提出。

9.3.1 Basic Paxos

Basic Paxos用于就单个值达成共识。

角色

  • Proposer:提出值
  • Acceptor:接受或拒绝值
  • Learner:学习最终决定的值

阶段

  • Prepare阶段(Phase 1a):Proposer发送Prepare请求,包含提案编号
  • Promise阶段(Phase 1b):Acceptor回复Promise,承诺不再接受编号更小的提案
  • Accept阶段(Phase 2a):Proposer发送Accept请求,包含提案编号和值
  • Accepted阶段(Phase 2b):Acceptor回复Accepted,接受提案

工作流程

1. Proposer发送Prepare(n)
2. Acceptor回复Promise(n, last_accepted_value)
3. Proposer选择值v(如果有last_accepted_value,选择它;否则选择自己的值)
4. Proposer发送Accept(n, v)
5. Acceptor回复Accepted(n, v)
6. 当大多数Acceptor回复Accepted时,值v被决定

优势

  • 正确性有数学证明
  • 可以处理节点故障

局限

  • 实现复杂
  • 难以理解
  • 性能不高

9.3.2 Multi-Paxos

Multi-Paxos用于就多个值达成共识。

优化

  • 选择一个固定的Leader(Proposer)
  • Leader可以跳过Prepare阶段,直接发送Accept请求
  • 提高性能

工作流程

1. 选举Leader
2. Leader直接发送Accept(n, v)
3. Acceptor回复Accepted(n, v)
4. 当大多数Acceptor回复Accepted时,值v被决定

9.4 Raft算法

Raft是Paxos的简化版本,由Diego Ongaro和John Ousterhout提出。

9.4.1 Leader选举

工作流程

1. 所有节点初始为Follower状态
2. 如果在超时时间内没有收到Leader的心跳,Follower变为Candidate
3. Candidate增加任期(term),向其他节点发送VoteRequest
4. 如果收到大多数节点的投票,Candidate变为Leader
5. Leader定期发送心跳,维持领导地位

投票规则

  • 每个任期只能投一票
  • 先收到请求的节点先投票
  • 只有日志至少和投票者一样完整的节点才能成为Leader

9.4.2 日志复制

工作流程

1. 客户端发送请求到Leader
2. Leader将请求追加到本地日志
3. Leader发送AppendEntries请求到Follower
4. Follower追加日志到本地
5. 当大多数节点追加成功后,Leader提交日志,应用到状态机
6. Leader通知Follower提交日志

日志匹配

  • 如果两个日志在某个索引处的条目相同,则它们在该索引之前的所有条目都相同
  • 如果两个日志在某个索引处的条目相同,则它们的任期也相同

日志同步

  • Leader维护每个Follower的nextIndex和matchIndex
  • nextIndex:下一个要发送给Follower的日志索引
  • matchIndex:已经发送给Follower的最高日志索引
  • 如果AppendEntries失败,Leader递减nextIndex,重试

9.4.3 安全性保证

选举限制

  • 只有日志至少和投票者一样完整的节点才能成为Leader
  • 保证Leader拥有所有已提交的日志

日志匹配

  • 保证不同节点的日志一致性

Leader完整性

  • 保证已提交的日志不会丢失

9.4.4 Raft vs Paxos

特性RaftPaxos
可理解性
实现复杂度
性能中等中等
正确性证明
工业应用广泛较少

9.5 共识算法的应用

9.5.1 分布式锁

工作原理

  • 使用共识算法选举Leader
  • Leader持有锁
  • Leader故障时,重新选举Leader

示例

  • etcd使用Raft实现分布式锁
  • ZooKeeper使用ZAB(类似Paxos)实现分布式锁

9.5.2 原子提交

工作原理

  • 使用共识算法就事务的提交或回滚达成一致
  • 保证跨节点的事务一致性

示例

  • CockroachDB使用Raft实现分布式事务
  • Google Spanner使用Paxos实现分布式事务

9.5.3 状态机复制

工作原理

  • 使用共识算法保证所有节点执行相同的操作序列
  • 所有节点维护相同的状态

示例

  • etcd使用Raft实现状态机复制
  • Consul使用Raft实现状态机复制

重要知识点

知识点1:一致性模型是权衡

不同的一致性模型提供不同程度的保证。线性一致性最强但性能最低,最终一致性最弱但性能最高。应该根据业务需求选择合适的一致性模型。

知识点2:共识问题无法完全解决

FLP不可能定理指出,在异步系统中,如果存在节点故障,共识问题无法完全解决。共识算法必须做出某种假设,如部分同步或故障检测。

知识点3:Raft比Paxos更易理解和实现

Raft是Paxos的简化版本,具有相同的正确性保证,但更易理解和实现。工业界更倾向于使用Raft。

知识点4:共识算法的应用广泛

共识算法可以用于Leader选举、分布式锁、原子提交、状态机复制等场景。是现代分布式系统的基础。

知识点5:一致性与性能是权衡

强一致性需要等待所有节点确认,性能低;弱一致性不需要等待所有节点,性能高。应该根据业务需求,在一致性和性能之间权衡。

常见误区

误区1:认为线性一致性总是必要的

线性一致性虽然语义简单,但性能低。对于很多应用,因果一致性或最终一致性已经足够,不需要使用线性一致性。

误区2:认为共识算法可以解决所有问题

共识算法只能解决单值共识问题。对于多值共识,需要使用Multi-Paxos或Raft。对于更复杂的问题,需要其他机制。

误区3:认为Paxos比Raft更好

Paxos和Raft具有相同的正确性保证,但Raft更易理解和实现。工业界更倾向于使用Raft。

误区4:忽视共识算法的性能影响

共识算法需要大多数节点确认,性能开销大。应该根据业务需求,选择合适的共识算法和配置。

误区5:认为共识算法可以处理拜占庭故障

Paxos和Raft只能处理崩溃故障,不能处理拜占庭故障。对于拜占庭故障,需要使用专门的拜占庭容错算法。

实践应用

案例1:etcd的共识实现

etcd是一个分布式键值存储系统,使用Raft实现共识。

Leader选举

  • 使用Raft的Leader选举机制
  • Leader负责处理所有写请求

日志复制

  • 使用Raft的日志复制机制
  • 保证所有节点的数据一致

应用

  • Kubernetes使用etcd存储集群状态
  • CoreDNS使用etcd存储DNS记录

关键经验

  • Raft易于理解和实现
  • etcd是工业界广泛使用的共识系统
  • 共识算法是分布式系统的基础

案例2:CockroachDB的分布式事务

CockroachDB是一个分布式SQL数据库,使用Raft实现分布式事务。

范围分区

  • 数据按范围分区
  • 每个分区使用Raft复制

分布式事务

  • 使用Raft实现原子提交
  • 保证跨分区的事务一致性

并行提交

  • 优化事务提交性能
  • 减少延迟

关键经验

  • 共识算法可以用于分布式事务
  • Raft可以实现高性能的分布式数据库
  • 并行提交可以提高性能

案例3:ZooKeeper的共识实现

ZooKeeper是一个分布式协调服务,使用ZAB(类似Paxos)实现共识。

Leader选举

  • 使用ZAB的Leader选举机制
  • Leader负责处理所有写请求

数据复制

  • 使用ZAB的数据复制机制
  • 保证所有节点的数据一致

顺序保证

  • 保证操作的顺序性
  • 用于分布式锁、配置管理等

关键经验

  • ZAB是Paxos的变体
  • ZooKeeper是工业界广泛使用的协调服务
  • 共识算法可以用于协调服务

本章小结

本章深入探讨了一致性与共识的核心概念。

一致性模型:线性一致性最强但性能最低,顺序一致性次之,因果一致性保证因果关系,最终一致性最弱但性能最高。

共识问题:多个节点就某个值达成一致。FLP不可能定理指出,在异步系统中,共识问题无法完全解决。

Paxos算法:经典的共识算法,正确性有数学证明,但实现复杂、难以理解。

Raft算法:Paxos的简化版本,更易理解和实现,工业界广泛使用。

共识算法应用:可以用于Leader选举、分布式锁、原子提交、状态机复制等场景。

选择一致性模型时,应该根据业务需求、性能要求、可用性要求等因素综合考虑。共识算法是分布式系统的基础,理解其原理对于设计正确的分布式系统至关重要。

下一章,我们将探讨批处理,这是处理大规模数据的重要手段。批处理系统可以高效地处理海量数据,支持复杂的数据分析和转换。