作者: andylin02
学习章节:第23章 管理关键状态(Managing Critical State)
关键词:分布式共识、Paxos、Raft、Chubby、CAP理论、强一致性、领头人选举、分布式锁、原子广播
一、引言:当“靠谱”需要节点们“说好”
“严格来讲,在有限时间内解决异步式分布式共识问题是不可能的。”——Fischer, Lynch, Patterson (1985)
在大型分布式系统中,可靠性来自复制——一份数据存于多个节点,一个请求可以被多个服务器处理。然而,复制带来了一个根本性问题:当节点之间出现分歧时,系统如何判断“正确答案”?
这就是分布式共识要解决的问题。本章探讨的核心命题是:如何让多个节点在网络不可靠、节点可能随时失效的情况下,就某个“值”达成不可撤销的一致意见?——这正是“不可靠”世界里建立“可靠”秩序的核心答案。
二、核心观点速览
| 维度 | 核心要点 |
|---|---|
| 分布式共识的定义 | 多个节点就一个值达成一致,即使部分节点失效,也能保证安全性(safety)和活性(liveness) |
| CAP定理 | 一个分布式系统不可能同时满足一致性、可用性和分区容错性——三者最多取其二 |
| BASE理论 | 基本可用(Basically Available)、软状态(Soft State)、最终一致性(Eventual Consistency)——用“最终一致”换取可用性 |
| 关键状态的正确性要求 | 系统设计师不能通过牺牲正确性来满足可靠性或性能的要求,尤其是在处理关键数据时 |
| Paxos的角色 | 共识算法领域的“老祖宗”,严谨但极其晦涩难懂 |
| Raft的角色 | 为工程师而生的共识算法,通过分解子问题实现可理解性 |
| 协调服务的模式 | 将共识算法封装为独立服务(Chubby、ZooKeeper、etcd),上层应用作为客户端使用 |
| 分布式共识的应用场景 | 领头人选举、组成员信息管理、分布式锁和租约、可靠分布式队列、原子广播 |
三、详细内容拆解
3.1 为什么需要分布式共识?从单点故障到集群一致
在集中式单机部署中,单点故障问题无法避免——一台机器宕机,整个服务瘫痪。引入集群可以解决可用性问题,但带来了一个新的、更深层的问题:多节点之间的数据如何保证一致性?
集群部署引发的一系列“灵魂拷问”包括:
集群中拥有多个节点,如何解决多个节点写入时的冲突?
集群内某些节点出现故障时,怎么保证对外服务的可用性?
集群发生故障转移时,如何保证新主拥有旧主的所有数据?
集群内发生网络分区问题时,如何避免集群出现脑裂问题?
使用读写分离时,如何保障多节点间读到的数据完全一致?
这些问题的本质,都可以归结为分布式共识问题的不同变种。而共识算法(Paxos和Raft)正是为这一系列问题提供的通用解决方案。
3.2 理论基础:CAP定理与BASE理论
CAP定理(Consistency, Availability, Partition tolerance)是分布式系统的“不可能三角”——一个分布式系统不可能同时满足以下三个要求:
| 维度 | 含义 |
|---|---|
| C(一致性) | 每个节点上所见数据是一致的 |
| A(可用性) | 每个节点都可以访问数据 |
| P(分区容错性) | 可以承受网络分区问题 |
由于网络分区是分布式系统的常态(P几乎无法避免),系统必须在C和A之间做出权衡——要么牺牲一致性换取可用性,要么牺牲可用性保证强一致性。
BASE理论则描述了牺牲强一致性后的“软状态”系统形态:
Basically Available(基本可用):系统能够响应请求,但可能返回陈旧数据
Soft State(软状态):副本之间的数据不一致是可接受的
Eventual Consistency(最终一致性):经过一段时间后,所有副本最终会达到一致
核心权衡:系统设计师不能通过牺牲正确性来满足可靠性或性能的要求,尤其是在处理关键数据时。假设某个系统处理财务交易——可靠性和性能在最终结果不正确的情况下一文不值。因此,对于关键状态(如财务数据、锁状态、集群元数据),必须选择强一致性;对于非关键数据,可以选择最终一致性换取更好的可用性。
3.3 分布式共识算法:从Paxos到Raft
分布式共识算法允许一组节点像一个整体一样一起工作,即使其中的一些节点出现故障也能够继续工作,其正确性主要源于复制状态机的性质:一组Server的状态机计算相同状态的副本,即使有一部分Server宕机了它们仍然能够继续运行。
3.3.1 Paxos协议:分布式一致性的“圣杯”
Paxos算法由Leslie Lamport于1990年提出,是分布式一致性算法中的经典之作。其核心思想是通过一系列角色和阶段来确保一致性:
| 角色 | 职责 |
|---|---|
| Proposer(提议者) | 提出新的提案或更新请求 |
| Acceptor(接受者) | 参与表决,决定是否接受某个提案。多数派的Acceptor构成的集合称为Quorum |
| Learner(学习者) | 从Acceptors那里获取最终决定的值并进行同步,不参与决策过程本身 |
Paxos的两阶段核心流程:
| 阶段 | 操作 | 目标 |
|---|---|---|
| Prepare | Proposer生成唯一提案编号,向所有Acceptor发送Prepare请求 | 锁定未来接受范围,阻止旧提案干扰 |
| Promise | Acceptor若未响应过更高编号的提案,则承诺不再接受比当前pre_num小的提案,并回复Promise响应 | 确保只有一个最新提案会被考虑 |
| Accept | Proposer收到多数Acceptors的Promise后,发送Accept请求 | 尝试让多数Acceptors接受该提案 |
| Ack | Acceptor若符合规则,接受此提案并持久化存储,回复Ack响应 | 确认提案已被多数Acceptors正式接受 |
| Learn | Learners从Acceptors获取最新的被接受的提案值并进行同步 | 传播最终一致的结果 |
Paxos的特点总结:
| 优点 | 缺点 |
|---|---|
| 极强的容错能力,能容忍高达(n-1)/2个节点的失效 | 算法相对复杂,难以理解和实现 |
| 理论上证明了其正确性和活性 | 存在活锁风险(如长时间无法选出领导者) |
| 严格的数学基础和理论支持 | 性能开销较大,尤其在广域网环境下 |
Paxos被称为分布式一致性协议的“老祖宗”,是诸多分布式一致性协议的“老祖宗”。但它也以其极度的晦涩难懂,劝退了一代又一代的工程师,被称为“神谕般的算法”。
3.3.2 Multi Paxos:对Basic Paxos的优化
Basic Paxos只能就单个值达成共识。Multi Paxos在此基础上做了扩展,允许一个节点被选为领导者,负责协调其他节点进行一系列提案的共识。虽然Multi Paxos通过减少通信量提高了性能,但仍然存在单点故障和选举新领导者的开销问题。
3.3.3 Raft:为可理解性而生的共识算法
Raft算法由斯坦福大学的Diego Ongaro和John Ousterhout于2013年提出,论文题为《In Search of an Understandable Consensus Algorithm》——其设计目标从标题就可见一斑。Raft在保证与Paxos同等容错能力和性能的前提下,以其“易于理解”的特性赢得了广泛认可。
不同于Paxos算法直接从分布式一致性问题出发推导出来,Raft算法则是从多副本状态机的角度提出,用于管理多副本状态机的日志复制。Raft将一致性分解为多个子问题:
| 子问题 | 核心逻辑 |
|---|---|
| Leader选举 | 系统中所有节点以Follower身份开始,通过投票机制选举出一个Leader |
| 日志复制 | Leader接收客户端的请求,将其转化为日志条目,并复制到所有Follower |
| 安全性 | 通过特定的日志条目提交规则和一致性检查,确保所有节点上的日志保持一致 |
Raft通过任期选举简化了模型,所有节点均可扮演以下三种角色之一,且角色会根据情况进行动态转换:
| 角色 | 职责 |
|---|---|
| Follower(跟随者) | 初始状态,被动响应来自Leader或其他Candidate的RPC请求 |
| Candidate(候选人) | 当Follower在超时时间内未收到Leader的心跳时,切换为此角色并发起选举 |
| Leader(领导者) | 获得多数票后成为Leader,负责处理所有客户端请求和日志复制 |
Raft将领导者和跟随者两种角色明确区分开来,并引入了日志复制和安全性等概念,通过这种分解方式显著降低了理解成本。
3.4 Paxos vs Raft:核心对比
| 对比维度 | Paxos | Raft |
|---|---|---|
| 核心特点 | “神谕般的算法”,数学严谨 | “为工程师设计的算法”,分解清晰 |
| 可理解性 | 较低,实现复杂度高 | 较高,设计简洁 |
| 实现难度 | 高,需要严格的数学证明 | 低,易于编码和调试 |
| 角色设计 | Proposer、Acceptor、Learner(偏学术化) | Leader、Candidate、Follower(偏工程化) |
| 日志提交方式 | 允许多条日志乱序提交,支持并行处理 | 要求日志严格按顺序执行,串行确认 |
| 理论根基 | 直接从分布式一致性问题推导 | 从多副本状态机角度提出 |
| 工程落地影响 | 催生了Chubby、ZooKeeper的Zab协议 | 催生了etcd、TiDB、Consul等主流产品 |
工程选型的核心权衡:
Paxos的优势在于更高的并发处理能力和更快的故障恢复速度。以OceanBase为例,选择Paxos而非Raft的核心考量包括:
更高并发:Paxos允许多条日志乱序提交,支持并行事务,不会成为并发瓶颈
更好可用性:Paxos协议下,一台机器新上线时能很快提供服务,不需要等待前面的所有日志确认
避免链式阻塞:Raft的顺序投票策略在存在网络抖动时,可能导致后续事务阻塞在内存中,引发链式反应甚至循环阻塞
实际应用中的选择建议:
| 适用场景 | 推荐算法 | 理由 |
|---|---|---|
| 对一致性要求极高的金融/数据库系统 | Paxos | 并发处理能力强,容错经过长期检验 |
| 大多数分布式系统(注册中心、配置管理) | Raft | 易于理解和实现,开发效率高 |
| 需要与etcd、TiDB等生态集成的场景 | Raft | 开源生态完善,社区活跃 |
3.5 协调服务(Coordination Service)模式
在实际工程中,直接实现共识算法是极其困难的——Paxos的晦涩和高复杂度使其实现门槛极高。因此,Google的实践智慧是:将共识算法封装为一个独立的协调服务,上层应用作为该服务的客户端。
协调服务是一个通过共识实现容错的复制协调器——一个小的、高可用的、强一致性的存储系统,分布式应用用它来共享信息和协调操作。
协调服务的典型使用场景:
谁是当前的Leader?
最新的配置是什么?
这个锁当前被谁持有?
哪些服务器当前存活?
💡为什么这些场景必须使用共识算法?如果两个节点都认为自己是Leader,它们会独立接受写入请求,系统状态将发生分裂;如果节点读到过期的配置,它可能将请求路由到已经不存在的服务器。强一致性在这里不是可选项,而是必选项。
三种主流协调服务的对比:
| 特性 | Chubby | ZooKeeper | etcd |
|---|---|---|---|
| 组织 | Google内部 | Yahoo开源 | CoreOS开源 |
| 底层共识 | Paxos | Zab(类Paxos) | Raft |
| 接口 | 分布式文件系统接口 | znode树 | HTTP+JSON |
| 核心抽象 | 文件和锁 | 临时节点+监听 | 键值存储+租约 |
| 典型应用 | GFS、Bigtable、MapReduce | Hadoop、Kafka | Kubernetes |
3.6 Google Chubby:分布式共识的经典实践
Chubby是Google内部设计的锁服务和配置存储系统,首次在2006年Mike Burrows的论文中公开描述。GFS需要一个选举主节点的方法,Bigtable需要协调tablet分配,MapReduce需要选举主任务跟踪器——Chubby为所有这些系统提供了一个共享的、精心设计的基础。
Chubby的架构:
| 设计要素 | 具体实现 |
|---|---|
| 单元(Cell) | 一个Chubby部署被称为一个单元,默认由5个副本组成 |
| Master选举 | 通过Paxos从5个副本中选举出一个Master |
| 读写分离 | Master负责处理所有客户端请求;其他副本参与共识,但重定向请求到Master |
| 容错能力 | 需要3/5的副本存活才能正常工作,可容忍2个并发故障 |
| 跨单元备份 | 每几小时将整个单元数据库备份到GFS,以防单元内所有副本的灾难性丢失 |
为什么选择5个副本?在大型数据中心环境中,两个并发故障并不罕见,但三个并发故障很少见。因此5副本可以容忍2个故障,是一个工程上的最优选择。
Chubby的接口设计:
文件系统接口:Chubby暴露一个层次化命名空间,锁、配置数据、服务地址都作为文件存储
锁即文件:锁就是文件,持有锁意味着打开文件
租约(Lease)机制:客户端打开文件时获得一个租约——对其缓存副本有效的时间保证
缓存失效:Master在文件被写入时向其他客户端发送缓存失效通知
故障恢复:如果Master失效,新Master选举产生后会广播新的epoch,客户端有一个宽限期重新连接;宽限期内未重连的客户端,其会话和锁将被释放
Chubby的设计深刻影响了后续的开源协调服务——ZooKeeper和etcd都借鉴了Chubby的核心理念。
3.7 分布式共识的核心应用场景
许多分布式系统问题最终都可以归结为分布式共识问题的不同变种:
| 应用场景 | 问题本质 | 核心要求 |
|---|---|---|
| 领头人选举 | 在分布式系统中确定唯一的Leader | 等价于分布式共识问题 |
| 组成员信息管理 | 维护动态变化的成员列表 | 多节点就成员列表达成一致 |
| 分布式锁 | 保证多个工作进程不会操作同一资源 | 使用可续期租约(renewable lease)防止进程崩溃后锁被无限期持有 |
| 可靠分布式队列 | 确保消息的顺序性和不丢失 | 需要共识保证顺序 |
| 原子广播 | 所有节点按相同顺序接收消息 | 共识解决的是“决定值”,原子广播解决的是“决定顺序” |
💡关键警示:任何临时解决共识问题的方法(如心跳、谣言协议)在实践中都会遇到可靠性问题。应该仅仅采用经过正式正确性证明的分布式共识算法来解决,还要确保算法的实现经过了大量测试。
3.8 分布式共识的核心权衡与设计考量
在实际工程中应用分布式共识时,需要关注以下关键维度:
① 正确性 > 性能
在处理关键数据时,系统设计师不能通过牺牲正确性来满足可靠性或者性能的要求。假设某个系统处理财务交易——可靠性和性能在最终结果不正确的情况下一文不值。
② 副本数量的选择
多数共识算法要求Quorum=多数派。例如5节点集群可以容忍2个故障,3节点集群可以容忍1个故障。更多的节点提供更高的容错能力,但也会增加通信开销。
③ 租约替代无限期锁
在实践中,需要使用可续期租约(renewable lease)而不是无限期锁,以防止某个进程崩溃后锁被无限期持有,导致死锁。
四、第23章知识点脑图总结
五、总结:一句话记住本章
分布式共识 = 让多个节点在不可靠网络中就某个值达成不可撤销的一致——用经过正式证明的共识算法(Paxos/Raft),封装为协调服务,让上层应用无需自己实现就能享受强一致性的保障。
| 关键点 | 一句话概括 |
|---|---|
| 分布式共识的必要性 | 多节点在不可靠环境下如何就一个值达成一致,是可靠分布式系统的基础问题 |
| CAP定理 | 一致性、可用性、分区容错性三者最多取其二——P几乎无法避免,必须在C和A间权衡 |
| BASE理论 | 用“最终一致性”换取基本可用性,适合非关键数据 |
| Paxos的定位 | 共识算法的“老祖宗”,数学严谨但晦涩难懂 |
| Raft的定位 | 为可理解性而生的共识算法,将复杂问题分解为Leader选举+日志复制+安全性 |
| 核心应用场景 | 领头人选举、组成员管理、分布式锁、可靠队列、原子广播 |
| 协调服务模式 | 将共识算法封装为独立服务(Chubby/ZooKeeper/etcd),上层应用作为客户端 |
| 关键警示 | 不要使用心跳、谣言协议等临时方案处理共识问题——必须用经过正式证明的算法 |
行动建议:
本周内完成:审视系统中的关键状态,识别哪些数据需要强一致性保证(如Leader选举状态、分布式锁、配置元数据),哪些可以接受最终一致性
一个月内完成:如果系统需要协调服务,评估引入etcd/ZooKeeper等成熟方案而非自己实现;为现有协调服务建立监控,关注共识层面的健康状况
一个季度内完成:设计租约(lease)机制替代无限期锁,防止进程崩溃后死锁;在系统架构中明确记录“为什么选Paxos/Raft”的决策依据
长期坚持:在系统设计阶段,将共识算法选型作为架构评审的必选项;保持对分布式共识领域的持续学习(Raft可理解性、Multi-Paxos优化、EPaxos等新方向)
六、高频考点自测
问题1:CAP定理指出分布式系统存在哪三个不可兼得的约束?
参考答案:CAP定理指出分布式系统不可能同时满足以下三个要求:①一致性(Consistency)——每个节点上所见数据是一致的;②可用性(Availability)——每个节点都可以访问数据;③分区容错性(Partition tolerance)——可以承受网络分区问题。在网络分区几乎不可避免的分布式环境中,系统必须在一致性和可用性之间做出权衡。
问题2:Paxos协议和Raft协议的核心区别是什么?
参考答案:Paxos协议由Lamport在1990年提出,是分布式一致性算法的经典,数学严谨但晦涩难懂。Raft协议由Ongaro和Ousterhout在2013年提出,旨在提供更易理解的共识算法。最关键的设计差异在于:Paxos允许多条日志乱序提交,支持并行处理;Raft要求日志严格按顺序执行,只有前一个日志被确认后才能确认后一个日志。Paxos适合需要高并发处理能力的场景(如金融数据库),Raft则因其可理解性和易实现性更适合大多数分布式系统。
问题3:Chubby的架构是怎样的?为什么需要5个副本?
参考答案:Chubby是Google内部的锁服务和配置存储系统,一个单元由5个副本组成。通过Paxos从5个副本中选举出一个Master,Master负责处理所有客户端请求;其他副本参与共识但将请求重定向到Master。需要3/5的副本存活才能正常工作,因此可容忍2个并发故障。选择5个副本的原因是在大型数据中心环境中,两个并发故障并不罕见,但三个并发故障很少见,因此5副本是容错能力与资源开销之间的工程最优选择。
问题4:分布式共识的典型应用场景有哪些?为什么不能用临时方案替代?
参考答案:典型应用场景包括:领头人选举、组成员信息管理、分布式锁和租约机制、可靠的分布式队列和消息传递、原子广播等。任何临时解决这类问题的方法(如心跳、谣言协议)在实践中都会遇到可靠性问题,因为它们在网络分区或节点故障时无法保证一致性。这些问题的本质都是分布式共识问题的变种,应该仅仅采用经过正式正确性证明的分布式共识算法来解决,还要确保算法的实现经过了大量测试。
问题5:什么是协调服务模式?为什么在实践中推荐使用这种模式?
参考答案:协调服务是一个通过共识实现容错的复制协调器——一个小的、高可用的、强一致性的存储系统,分布式应用用它来共享信息和协调操作。将共识算法封装为独立的协调服务(如Chubby、ZooKeeper、etcd),上层应用作为该服务的客户端。这种模式之所以重要,是因为直接实现共识算法极其困难——Paxos的晦涩和高复杂度使其实现门槛极高。通过使用成熟的协调服务,应用层可以享受强一致性保障,而无需自己从零实现复杂的共识算法。
七、延伸阅读推荐
《Google SRE 工作手册》第23章“Managing Critical State”:本章内容的工作手册版扩展
《The Part-Time Parliament》(Leslie Lamport,1998):Paxos算法的原始论文,以“希腊岛屿议会”的比喻描述
《In Search of an Understandable Consensus Algorithm》(Diego Ongaro & John Ousterhout,2013):Raft算法的原始论文
《The Chubby Lock Service for Loosely-Coupled Distributed Systems》(Mike Burrows,2006):Google Chubby的原始论文
ZooKeeper官方文档:https://zookeeper.apache.org
etcd官方文档:https://etcd.io
Google SRE官方书籍网站:https://sre.google
《SRE 中文社区》:https://www.srenow.cn
学习下一章预告:第24章“分布式时间线服务”——深入Google的内部数据系统如何存储和管理海量时序数据,这是支撑大规模监控和调试系统的关键基础设施。
本文为个人学习笔记,仅用于知识分享。如有错误,欢迎指正。
👍🏻 点赞 + 收藏 + 分享,让更多开发者看到这篇深度解析!❤️ 如果觉得有用,请给个赞支持一下作者!