分布式理论、算法与协议是理解分布式系统的基础。学习这部分内容时,不建议只背结论,更重要的是理解不同方案在一致性、可用性、容错、共识、性能和工程复杂度之间的取舍。
适合谁看
- 想系统理解分布式一致性、共识算法和数据分布的后端开发者。
- 准备分布式系统、系统设计、后端架构面试的同学。
- 对 CAP、BASE、Paxos、Raft、ZAB、Gossip 等概念只停留在“背过”的读者。
- 需要理解 ZooKeeper、Redis Cluster、分布式缓存和服务发现底层机制的工程师。
分布式理论、算法与协议是理解分布式系统的基础。学习这部分内容时,不建议只背结论,更重要的是理解不同方案在一致性、可用性、容错、共识、性能和工程复杂度之间的取舍。
几个服务节点都说自己是对的,客户端该信谁?
在日常后端系统里,这个问题通常没有这么极端。Redis 主从、ZooKeeper、etcd、Nacos、数据库复制,更多遇到的是机器宕机、网络抖动、磁盘故障、进程重启。节点一般不会故意骗你,它只是没响应、响应慢,或者暂时和集群断开了。
拜占庭将军问题讨论的是更麻烦的一类情况:系统里有节点会表现得不可预测,甚至可能给不同对象发送互相矛盾的信息。
这就是它在分布式系统里的价值。古代军事故事只是表达手段,真正要讲的是“在不可靠成员中达成一致”。
如果你正在学习 Raft、ZAB、ZooKeeper、etcd 这类常见协调系统,需要先区分两类故障模型:它们通常处理的是崩溃故障和网络分区,不假设节点恶意撒谎;拜占庭问题讨论的是更强的故障模型。想看非拜占庭场景里的共识,可以继续读 Raft 算法详解 和 ZAB 协议详解。
一个定时任务部署了 3 个实例,到了凌晨 2 点,到底谁来跑这批任务?
如果 3 个实例都跑,数据可能被重复处理;如果 3 个实例都等别人跑,任务就会漏掉。缓存集群、消息队列、配置中心、分布式锁也会遇到类似问题:节点多了以后,系统必须有人决定“谁负责什么”“谁现在还活着”“这次变更按什么顺序生效”。
这就是分布式系统里的协调问题。
不过,这里要先区分两件事:只选出一个执行者,和业务只生效一次。
选主、分布式锁或数据库抢占可以减少多个实例同时执行,但无法单独保证端到端的 exactly-once。执行节点可能已经处理成功,却在更新任务状态前宕机;调度系统为了避免漏任务,只能再次派发。Kubernetes CronJob 官方文档也提醒过,CronJob 创建 Job 的时间是近似的,某些情况下可能创建两个 Job,也可能没有创建 Job,因此 Job 本身应该设计成幂等。
开始之前,先说两个常见的场景:
这两种场景的本质,都是需要建立一个从 key 到服务器/节点的稳定映射关系。
在分布式系统中,不同节点间共享状态是一个基本需求。
一种简单的方法是 集中式广播:由中心节点向所有其他节点同步信息。这种方式适合中心化系统,但存在明显缺陷:当节点数量增加时,同步效率下降(O(N) 复杂度),且过度依赖中心节点,存在单点故障风险。
分散式传播 的 Gossip 协议 提供了一种去中心化的替代方案。
如果你还不清楚 Leader/Quorum 和 Gossip 分别适合解决什么问题,可以先看 分布式协调详解。这篇 Gossip 文章只展开“状态如何传播并最终收敛”,不负责解释 Leader 选举、脑裂和 Fencing Token 这类强协调问题。
Paxos 算法是 Leslie Lamport(莱斯利·兰伯特)在 1990 年提出的一种分布式系统 共识 算法。这是最早被广泛认可的分布式共识算法之一(前提是不存在拜占庭将军问题,也就是没有恶意节点)。
为了介绍 Paxos 算法,兰伯特专门写了一篇幽默风趣的论文。在这篇论文中,他虚拟了一个叫做 Paxos 的希腊城邦来更形象化地介绍 Paxos 算法。
不过,审稿人并不认可这篇论文的幽默。于是,他们就给兰伯特说:“如果你想要成功发表这篇论文的话,必须删除所有 Paxos 相关的故事背景”。兰伯特一听就不开心了:“我凭什么修改啊,你们这些审稿人就是缺乏幽默细胞,发不了就不发了呗!”。
本文由 SnailClimb 和 Xieqijun 共同完成。
在如今的互联网架构中,为了扛住海量流量,系统往往需要横向堆机器。机器一多,宕机、断网这些破事就成了家常便饭。怎么让这群随时可能掉线的服务器保持步调一致,不对外提供错乱的数据?这就轮到分布式共识算法出场了。
作为一款极其优秀的分布式协调框架,ZooKeeper 的高可用和数据一致性备受业界推崇。很多人误以为 ZooKeeper 使用的是大名鼎鼎的 Paxos 算法,但实际上,它的“灵魂”是一个专门为其定制的共识协议——ZAB(ZooKeeper Atomic Broadcast,原子广播协议)。
ZAB 并非像 Paxos 那样是通用的分布式一致性算法,它是一种特别为 ZooKeeper 设计的、支持崩溃可恢复的原子消息广播算法。基于 ZAB 协议,ZooKeeper 实现了一种主备模式的架构,来保持集群中各个副本之间的数据一致性。