Skip to content

分布式理论

概念

分布式系统是指多台计算机通过网络协同工作,对外表现为一个整体的系统。核心挑战在于:网络不可靠、节点可能宕机、时钟无法完全同步。

关键术语

术语含义
节点(Node)分布式系统中的一台独立机器或进程
分区(Partition)网络故障导致节点之间无法通信
副本(Replica)同一份数据的多个拷贝,用于容错和提升读性能
共识(Consensus)多个节点就某个值达成一致的过程
幂等性(Idempotency)同一操作执行多次与执行一次效果相同

核心原理

1. CAP 定理

CAP 由 Eric Brewer 于 2000 年提出,指出分布式系统无法同时满足以下三个特性,最多只能满足其中两个:

  • C(Consistency,一致性):所有节点在同一时刻看到的数据完全一致(强一致性)
  • A(Availability,可用性):每个请求都能收到响应(不保证数据是最新的)
  • P(Partition Tolerance,分区容错):网络发生分区时,系统仍能继续运行

为什么 P 必须选?

在真实的分布式环境中,网络分区是客观存在且无法完全避免的——网线故障、交换机宕机、跨机房延迟都可能造成分区。放弃 P 意味着系统在网络抖动时直接停止服务,这在生产环境中不可接受。因此 P 是必选项,真正的选择只在 CP vs AP

CP vs AP 系统举例

类型代表系统行为
CPZooKeeper、etcd、HBase网络分区时拒绝写请求,保证数据一致
APEureka、Cassandra、CouchDB网络分区时仍接受读写,允许数据短暂不一致

ZooKeeper 选择 CP:Leader 选举期间集群不可用,但数据强一致,适合配置中心、分布式锁。

Eureka 选择 AP:节点故障时不下线其他节点的注册信息,优先保证服务发现可用,适合微服务注册中心。


2. BASE 理论

BASE 是对 CAP 中 AP 方向的工程实践总结,由 eBay 架构师 Dan Pritchett 提出:

  • Basically Available(基本可用):允许响应时间变长或部分功能降级,核心功能仍然可用
  • Soft State(软状态):系统中的数据可以存在中间状态,不要求时刻一致
  • Eventually Consistent(最终一致性):数据在一段时间后会最终达到一致状态

BASE vs ACID 对比

维度ACIDBASE
适用场景单机/强一致性关系数据库分布式/高可用系统
一致性要求强一致性最终一致性
可用性发生冲突时可能阻塞优先保证可用性
代表系统MySQL、PostgreSQLDynamoDB、Cassandra
核心思想事务要么全做要么全不做接受短暂不一致,换取高可用

3. 一致性模型

从强到弱,常见的一致性模型如下:

模型定义代价典型应用
强一致性写完之后所有节点立即可见最新数据延迟高,可用性低ZooKeeper、etcd
顺序一致性所有节点看到的操作顺序相同,但不要求实时中等早期分布式数据库
因果一致性有因果关系的操作按顺序可见,无关操作可乱序较低MongoDB(因果会话)
最终一致性在没有新更新的前提下,数据最终会收敛一致最低DNS、Cassandra、S3

4. Paxos 算法

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

三种角色

  • Proposer(提案者):发起提案,请求集群就某个值达成共识
  • Acceptor(接受者):投票接受或拒绝提案
  • Learner(学习者):学习最终被接受的值,不参与投票

两阶段流程

阶段一:Prepare(准备阶段)

  1. Proposer 生成全局唯一编号 n,向多数派 Acceptor 发送 Prepare(n) 请求
  2. Acceptor 收到后,若 n 大于已见过的最大编号,则承诺不再接受编号小于 n 的提案,并返回已接受的最大编号提案

阶段二:Accept(接受阶段)

  1. Proposer 收到多数派响应后,选取编号最大的已接受值(若无则用自己的值),发送 Accept(n, value)
  2. Acceptor 若未承诺更高编号,则接受该提案并通知 Learner

Multi-Paxos

Basic Paxos 每次共识都需要两轮 RPC,开销较大。Multi-Paxos 优化:选出一个稳定的 Leader,后续日志直接跳过 Prepare 阶段,只执行 Accept,大幅减少通信轮次。

活锁(Live-Lock)问题 — 必背追问点

Basic Paxos 允许多个 Proposer 并发提案,可能出现互相抢占:

Proposer-A: Prepare(n=1) → 被多数派承诺
Proposer-B: Prepare(n=2) → 抢占,A 的 Accept(n=1) 被拒
Proposer-A: Prepare(n=3) → 反过来抢占 B
Proposer-B: Prepare(n=4) → 又抢回来 ... 无限循环,无人能进入 Accept 成功

两个 Proposer 交替提升编号,谁都无法完成 Accept,系统一直不终止——这正是 FLP 定理在 Paxos 上的体现。

解法:① Multi-Paxos 选出唯一稳定 Leader,只让一个 Proposer 提案;② 引入随机退避,抢占失败后随机等待再重试。这也是几乎所有工程实现都用 Multi-Paxos 而非 Basic Paxos 的核心原因。

为什么 Paxos 难理解

  • 原始论文《The Part-Time Parliament》用希腊议会隐喻,晦涩难懂,Lamport 后来又写了《Paxos Made Simple》补救
  • Basic Paxos 只定义了"如何就单个值达成共识",但没说清楚如何把它变成一个连续的日志复制系统(工程落地的关键),留给实现者大量空白
  • 角色、编号、承诺规则交织,缺乏明确的状态机描述——这正是 Raft 诞生的动机:用可理解性换取工程落地效率

5. Raft 算法

Raft 由 Diego Ongaro 和 John Ousterhout 于 2014 年提出,目标是比 Paxos 更易理解,被 etcd、TiKV、CockroachDB 广泛采用。

三种状态

  • Follower(跟随者):被动接收 Leader 的日志和心跳
  • Candidate(候选者):发起选举时的临时状态
  • Leader(领导者):负责处理所有客户端请求,复制日志

Leader 选举过程(ASCII 图)

初始状态:所有节点均为 Follower

  Node A [Follower]    Node B [Follower]    Node C [Follower]
      |                    |                    |
      |  超时未收到心跳      |                    |
      |                    |                    |
      v                    |                    |
  Node A [Candidate]       |                    |
      |                    |                    |
      |--- RequestVote(term=1) -->              |
      |--- RequestVote(term=1) ----------------->
      |                    |                    |
      |<-- VoteGranted ----                     |
      |<-- VoteGranted ----------------------------
      |                    |                    |
      v  获得多数票         |                    |
  Node A [Leader]          |                    |
      |                    |                    |
      |--- Heartbeat ------>                    |
      |--- Heartbeat -------------------------------->

日志复制流程

  1. 客户端向 Leader 发送写请求
  2. Leader 将日志条目追加到本地日志,并并行发送 AppendEntries 给所有 Follower
  3. 多数派(Quorum)写入成功后,Leader 提交该条目并应用到状态机
  4. Leader 在下次心跳中通知 Follower 提交

安全性保证

  • 选举限制:只有拥有最新日志的节点才能成为 Leader(日志比较:term 更大,或 term 相同但 index 更大)
  • 任期(Term):全局单调递增的逻辑时钟,用于检测过时信息

实际应用

系统用途
etcdKubernetes 集群元数据存储
TiKVTiDB 的分布式存储层
CockroachDB分布式 SQL 数据库
Consul服务发现与配置中心

Paxos vs Raft 对比 — 高频追问

两者都是解决分布式共识的算法,能力等价(Raft 可视为 Multi-Paxos 的一种工程化、强 Leader 化实现),但设计哲学不同:

维度PaxosRaft
设计目标理论正确性优先可理解性优先,易工程落地
LeaderBasic Paxos 无 Leader;Multi-Paxos 有但非强制强 Leader,所有写请求必须经 Leader
日志流向可乱序提交,允许日志空洞日志严格顺序、连续无空洞(Log Matching)
提案冲突多 Proposer 并发 → 可能活锁同一 term 只有一个 Leader,从根本上避免冲突
成员变更论文未明确定义,实现各异内置 Joint Consensus / 单节点变更方案
学习曲线陡峭,论文晦涩平缓,有完整论文 + 大量可视化
典型实现Chubby、OceanBase、Spanneretcd、TiKV、Consul、CockroachDB

一句话总结:Paxos 是共识问题的理论鼻祖与正确性标杆;Raft 是把 Multi-Paxos「强 Leader + 顺序日志 + 明确成员变更」工程化,牺牲一点灵活性换取可理解性和落地效率,因此现代系统新造轮子几乎都选 Raft。


6. ZAB 协议

ZAB(ZooKeeper Atomic Broadcast)是 ZooKeeper 专用的一致性协议,与 Raft 思路相近但有所不同。

核心流程

  • 崩溃恢复(Leader Election):Leader 宕机后,选出拥有最新 zxid(事务 ID)的节点作为新 Leader
  • 消息广播(Broadcast):类似两阶段提交,Leader 向所有 Follower 广播 Proposal,收到多数 ACK 后提交

ZAB vs Raft 对比

维度ZABRaft
设计目标ZooKeeper 专用通用共识算法
日志提交Follower 可不存完整历史必须有完整日志才能成为 Leader
顺序保证严格有序(FIFO)严格有序
易理解性较复杂更清晰,有完整论文

7. 一致性哈希

一致性哈希(Consistent Hashing)解决了传统取模哈希在节点增删时导致大量数据迁移的问题。

哈希环

将哈希空间组织成一个首尾相接的环(),节点和数据都映射到环上:

              0
           /     \
      300       60
   [NodeC]       [NodeA]
      |               |
     240           120
          [NodeB]
             180

数据按顺时针方向找到第一个节点进行存储。新增或删除节点时,只影响该节点相邻的数据,其余数据不受影响。

虚拟节点解决数据倾斜

真实部署中,节点数量少时哈希环分布不均,导致数据倾斜(某些节点负载远高于其他节点)。

解决方案:为每个物理节点创建多个虚拟节点(Virtual Node),分散映射到环上:

物理节点 NodeA → 虚拟节点 NodeA#1, NodeA#2, NodeA#3 ... 均匀分布在环上

虚拟节点数量越多,数据分布越均匀,通常每个物理节点配置 100~200 个虚拟节点。

实际应用

系统用途
Cassandra数据分片与副本放置
Amazon DynamoDB分区键路由
Nginx(一致性哈希模块)负载均衡
Memcached 客户端缓存节点路由

8. 分布式时钟

在分布式系统中,物理时钟无法做到完全同步(网络延迟、晶振漂移等原因),因此无法仅靠物理时间判断事件的先后顺序。逻辑时钟和混合时钟的目标是在不依赖绝对物理时间的前提下,准确追踪事件的因果关系。

Lamport Clock(兰伯特时钟)

  • 标量逻辑时钟,每个进程维护一个单调递增的计数器
  • 规则:本地事件发生时计数器加一;发送消息时附带当前计数器值;接收消息时取 max(本地计数器, 消息计数器) + 1
  • 局限:可以判断"先发生(happened-before)"关系,但无法区分并发事件——如果 a → bC(a) < C(b),但 C(a) < C(b) 不能推出 a → b

Vector Clock(向量时钟)

  • 每个进程维护一个长度为 N(进程数)的计数器向量
  • 既能判断因果关系,又能检测并发事件(两个事件互相不能比较大小即为并发)
  • DynamoDB、Riak 使用向量时钟进行冲突检测
  • 缺点:空间复杂度 ,进程数增加时开销显著

HLC(Hybrid Logical Clock,混合逻辑时钟)

  • 结合物理时间戳与逻辑计数器:物理时间提供粗粒度排序,逻辑计数器提供细粒度因果追踪
  • 与物理时间的偏差有上界,表示紧凑(
  • CockroachDB、YugabyteDB 采用 HLC
  • 优势:在保持因果追踪能力的同时,与真实时间的偏差可被控制在毫秒级

三种时钟对比

时钟类型能否判断因果能否检测并发空间复杂度典型应用
Lamport ClockO(1)简单排序场景
Vector ClockO(N)DynamoDB、Riak
HLC部分O(1)CockroachDB

9. FLP 不可能定理

结论:在异步系统中,即使只有一个进程可能发生故障,也不存在确定性的共识算法能保证在有限时间内终止。

工程含义:所有实际的共识算法(Paxos、Raft)都依赖超时机制和随机化来取得进展。FLP 定理告诉我们异步共识的理论极限,但实践中纯异步系统极为罕见,超时机制让算法在大多数情况下能正常工作。

FLP 的实际意义

理解 FLP 不可能定理有助于在面试中展示对分布式系统理论边界的认知:

  • 为什么 Raft/Paxos 需要超时? FLP 证明了在纯异步模型下共识不可解。引入超时(即部分同步假设)是工程上绕过 FLP 限制的标准做法。
  • 为什么选举有时会失败? 多个 Candidate 同时发起选举可能导致投票分裂(split vote),没有节点获得多数票。Raft 通过随机化选举超时来降低冲突概率,但理论上无法保证有限步内一定选出 Leader——这正是 FLP 定理的体现。
  • 工程妥协:实际系统通过引入故障检测器(Failure Detector)随机化来获得高概率的活性保证,虽然不是理论上的确定性终止,但在实践中足够可靠。

10. ZooKeeper vs etcd 选型对比

ZooKeeper 和 etcd 都是分布式协调服务,提供强一致性的配置存储、服务发现和分布式锁能力,但在协议、数据模型和生态上存在明显差异。

架构对比

维度ZooKeeperetcd
语言JavaGo
一致性协议ZABRaft
数据模型树形(类文件系统,ZNode)扁平 KV(键值对)
临时节点支持(Ephemeral Node)通过 Lease 实现
Watch 机制一次性触发,需重新注册持续 Watch,基于 Revision
事务支持Multi 操作Mini 事务(If-Then-Else)
性能读多写少场景优秀读写均衡
运维复杂度JVM 调优,相对复杂单二进制,运维简单
生态Hadoop/Kafka/HBase 生态Kubernetes/Cloud Native 生态

选型建议

  • 已有 Hadoop/Kafka 生态 → ZooKeeper
  • Kubernetes / 云原生项目 → etcd
  • 需要临时节点语义(如分布式锁)→ ZooKeeper 更自然
  • 追求运维简单 → etcd

ZooKeeper 分布式锁实现示例

1. 客户端在 /locks/resource 下创建临时顺序节点 /locks/resource/lock-000001
2. 获取 /locks/resource 下所有子节点,排序
3. 如果自己是最小节点 → 获得锁
4. 否则 → Watch 前一个节点(如 lock-000000)
5. 前一个节点删除(释放锁或会话超时)→ 收到通知,重新检查
6. 客户端断开连接 → 临时节点自动删除 → 锁自动释放

脑裂(Split-Brain)防御 — 必背追问点

面试一旦聊到主从、Sentinel、ZK、etcd,必追"脑裂怎么办?"——这道题问的是网络分区下两个 Leader 同时存活的解决方案。

脑裂是什么

脑裂 = 集群网络分区后,多个分区各自选出 Leader,同时对外写入,导致数据不一致。

典型场景:5 节点集群被网络分成 [3] + [2] 两边,老 Leader 在少数派 [2] 里没察觉自己被孤立,继续接受写请求;多数派 [3] 重新选了新 Leader 也接受写请求 → 两个 Leader 同时存在 → 网络恢复后数据冲突无法合并。

防御 4 大武器

武器 1:Quorum(多数派)— 最核心

公式(Dynamo / Cassandra)

含义解释
N副本总数
W写入成功最少节点数
R读取最少节点数

为什么 W + R > N 能防脑裂:任意一次"读"必定与任意一次"写"有至少 1 个节点重叠,所以一定能读到最新写入。

💡 N=5 时怎么设置

强一致:W=3, R=3(任意一次读写都过半数); ② 读多写少:W=4, R=2(读快,但写慢); ③ 写多读少:W=2, R=4(写快,但读慢)。 Raft / ZK 默认 W = ⌈N/2⌉ + 1(即过半数),即使被脑裂分割也只有多数派那边能写入。

武器 2:奇数节点 + 过半选举

为什么集群节点数必须奇数

节点数能容忍宕机脑裂分区最坏情况
31[2]+[1] → 多数派 [2] 能选主 ✅
41(和 3 一样!)[2]+[2] → 没有多数派,无法选主
52[3]+[2] → 多数派 [3] 能选主 ✅

结论:4 节点不仅没有比 3 节点容灾更好,反而可能脑裂卡死。生产部署一律奇数:3、5、7

武器 3:Witness(仲裁节点)— 跨机房必备

问题:跨机房部署 2 个机房,每个机房 2 节点(共 4),任意一边断网都会脑裂卡死。

解决方案:在第三个机房部署 1 个 Witness 节点(不存数据,只投票),变成 5 节点过半数选举:

机房 A: 2 节点 + 机房 B: 2 节点 + 机房 C: 1 Witness  (共 5 节点)

   网络分区时:
   - A 断网 → B(2) + C(1) = 3 ≥ 3 → ✅ 能选主
   - B 断网 → A(2) + C(1) = 3 ≥ 3 → ✅ 能选主
   - C 断网 → A(2) + B(2) = 4 ≥ 3 → ✅ 能选主
中间件Witness 名称
MongoDBArbiter(仲裁节点)
RabbitMQ Quorum QueueTie-breaker
SQL Server AlwaysOnFile Share Witness / Cloud Witness
Galera ClusterGarbd(galera arbitrator daemon)

武器 4:Fencing Token(栅栏令牌)— Martin Kleppmann 提出

问题:即使有 Quorum,老 Leader 在被废除后因 GC 暂停或网络延迟,依然可能向存储系统提交写请求 → 旧数据覆盖新数据。

解决方案:每次选主时,全局递增 token,存储层只接受 token ≥ 当前最大 token 的写请求:

时刻 T1: Leader-A 拿到 token=5,开始写
时刻 T2: Leader-A GC 暂停 30 秒
时刻 T3: 集群超时,选出 Leader-B,token=6
时刻 T4: Leader-B 写入 (token=6) → 存储接受
时刻 T5: Leader-A 苏醒,写入 (token=5) → 存储拒绝(5 < 6)

实战中谁支持

系统Fencing 实现
ZooKeepercversion / mzxid 单调递增
etcdrevision 单调递增(lease 续约带 revision)
Redis RedlockMartin 批评其没有 fencing token,所以不建议用 Redlock 做关键锁
HBaseRegionServer 心跳 + ZK 临时节点

主流中间件防脑裂手段一览(必背)

中间件防脑裂手段推荐部署
ZooKeeperZAB 协议 + 过半数选举 + zxid 递增3/5/7 节点奇数
etcdRaft + 过半数 + revision fencing3/5/7 节点奇数
Redis Sentinelquorum 配置 + min-replicas-to-write至少 3 个 Sentinel,且分散在 3 机房
Redis Clustergossip + 16384 slot + 故障转移过半数至少 3 主(最好 + 3 从)
KafkaController 选举走 ZK/KRaft,acks=all + min.insync.replicasmin.insync.replicas ≥ 2
MongoDB ReplicaSet过半数选主,Arbiter 凑奇数3 节点 PSS 或 PSA
MySQL MHA / MGRMGR 走 Paxos;MHA 靠 VIP + STONITHMGR 至少 3 节点
Elasticsearchdiscovery.zen.minimum_master_nodes(旧) / 7.x+ 自动 quorummaster 节点至少 3 个

⚠️ Redis Sentinel 经典脑裂场景

场景:1 主 2 从 + 3 Sentinel。主节点和所有客户端在机房 A,2 从 + 3 Sentinel 在机房 B。机房间网络断开 → ① B 中 Sentinel 过半数 → 提升从节点为新主; ② A 中老主仍然接受客户端写入(客户端没切换); ③ 网络恢复 → 老主成了从,A 期间的所有写入被丢弃

防御:配置 min-replicas-to-write 1 + min-replicas-max-lag 10——如果主节点没有至少 1 个从节点在 10 秒内确认主节点拒绝写入,从源头切断脑裂期间的写入。

黄金答题模板(必背)

面试官:怎么防脑裂?

:4 大武器组合拳: ① Quorum:W + R > N,写入必须过半数节点确认,少数派分区无法写入; ② 奇数节点:3/5/7 节点部署,避免 4 节点脑裂卡死; ③ 跨机房用 Witness:第三机房放仲裁节点,避免两机房对等分区; ④ Fencing Token:选主时全局单调递增 token,存储层只接受最新 token 的写请求,防止老 Leader 苏醒后写入旧数据; 实战中 ZK/etcd 都是 Quorum + 单调 revision 的标准方案;Redis Sentinel 必须配 min-replicas-to-write 才安全;Redlock 因为没有 fencing token,不建议做关键锁


面试常问 & 怎么答

Q1: CAP 定理是什么?为什么不能同时满足?举例说明 CP 和 AP 系统

答题思路(1 分钟版本)

CAP 定理指出,分布式系统无法同时保证一致性(C)、可用性(A)、分区容错(P)三者,最多满足其二。

为什么不能三者兼得?假设节点 A 和 B 之间发生网络分区,此时向 A 写入数据,B 无法同步。如果要保证 C,就必须拒绝 B 的读请求,牺牲 A;如果要保证 A,B 继续提供服务,但数据可能过期,牺牲 C。两者无法同时满足。

由于网络分区在生产中不可避免,P 必须保留,真正的取舍只在 CP vs AP:

  • CP 系统:ZooKeeper——选举期间拒绝写入,保证强一致,适合配置中心、分布式锁。
  • AP 系统:Eureka——节点故障时保留旧注册信息,优先可用,适合服务发现。

Q2: Raft 算法的核心流程?Leader 选举怎么做?

答题思路(1 分钟版本)

Raft 将一致性问题分解为三个子问题:Leader 选举、日志复制、安全性。

Leader 选举:节点初始为 Follower,超过选举超时未收到 Leader 心跳后,自增 term 转为 Candidate,向其他节点发 RequestVote 请求。获得多数票后成为 Leader,并立即发心跳阻止新选举。

选举安全性:投票时节点只给"日志不比自己旧"的 Candidate 投票,确保 Leader 一定拥有所有已提交的日志。

日志复制:客户端写请求发给 Leader,Leader 追加日志后并行发给 Follower,多数派写成功后提交,回复客户端。


Q3: Paxos 算法的原理?两阶段分别做什么?

答题思路(1 分钟版本)

Paxos 由 Lamport 提出,是分布式共识的理论基础,有 Proposer、Acceptor、Learner 三种角色,通过两阶段就单个值达成一致。

阶段一 Prepare:Proposer 生成全局唯一递增编号 n,向多数派 Acceptor 发 Prepare(n);Acceptor 若 n 大于见过的最大编号,就承诺不再接受更小编号的提案,并返回自己已接受的最大编号提案值。

阶段二 Accept:Proposer 收到多数派承诺后,若返回中已有被接受的值,就必须沿用编号最大的那个值(否则用自己的值),发 Accept(n, value);多数派接受后该值被选定。

关键约束:Proposer 必须"继承"已被接受的值——这保证了一旦某个值被多数派选定,后续所有提案都会收敛到同一个值,即共识的安全性

补充:Basic Paxos 多 Proposer 并发会活锁,工程上都用 Multi-Paxos——选出稳定 Leader,跳过 Prepare 直接 Accept。


Q4: Paxos 和 Raft 有什么区别?为什么现代系统多选 Raft?

答题思路(1 分钟版本)

两者能力等价,都能解决分布式共识,Raft 本质上可以看作 Multi-Paxos 的工程化实现,核心区别在设计哲学:

Leader 定位:Raft 是强 Leader,所有写请求必经 Leader;Basic Paxos 无 Leader,多个 Proposer 可并发提案,容易活锁。

日志结构:Raft 日志严格连续、无空洞(Log Matching 性质);Paxos 允许乱序提交和日志空洞,实现复杂。

成员变更:Raft 内置 Joint Consensus / 单节点变更方案;Paxos 论文没有明确定义,各实现自行发挥。

可理解性:Raft 的设计目标就是"可理解",有清晰的状态机和完整论文;Paxos 论文晦涩,工程落地空白多。

结论:Paxos 是理论鼻祖和正确性标杆(Google Chubby、Spanner、OceanBase 用),但现代新系统(etcd、TiKV、Consul、CockroachDB)几乎都选 Raft——用一点灵活性换取可理解性和落地效率。


Q5: 一致性哈希是什么?虚拟节点解决什么问题?

答题思路(1 分钟版本)

一致性哈希将哈希空间构成一个环,节点和数据都映射到环上,数据顺时针找最近节点存储。好处是新增或删除节点时,只有相邻的少量数据需要迁移,其余不受影响——传统取模哈希在节点数变化时几乎所有数据都要重新分配。

虚拟节点解决数据倾斜问题:节点少时环上分布不均,负载集中在少数节点。为每个物理节点创建多个虚拟节点均匀散布在环上,使数据分布更均匀,负载更平衡。Cassandra 和 DynamoDB 都使用了这一机制。


Q6: 分布式时钟有哪些?解决什么问题?

答题思路(1 分钟版本)

分布式系统中物理时钟无法完全同步,需要逻辑时钟来确定事件的先后顺序。

三种主要方案:Lamport Clock 是最简单的标量时钟,能判断因果关系但无法检测并发事件;Vector Clock 为每个进程维护一个计数器向量,既能判断因果又能检测并发,DynamoDB 和 Riak 使用它来做冲突检测,但空间复杂度 O(N);HLC 混合逻辑时钟结合物理时间和逻辑计数器,CockroachDB 使用它,兼顾了紧凑表示和因果追踪。

实际选型:大多数分布式数据库使用 HLC,分布式存储系统使用 Vector Clock,简单场景用 Lamport Clock 足够。


Q7: ZooKeeper 和 etcd 怎么选?

答题思路(1 分钟版本)

两者都是分布式协调服务,核心区别在协议、数据模型和生态。

ZooKeeper 使用 ZAB 协议,树形数据模型,原生支持临时节点和一次性 Watch,是 Hadoop/Kafka 生态的标配。etcd 使用 Raft 协议,扁平 KV 模型,持续 Watch 基于 Revision,是 Kubernetes 的核心组件。

选型建议:大数据生态(Kafka、HBase)选 ZooKeeper;云原生/K8s 生态选 etcd;需要分布式锁且已有 ZK 则继续用 ZK;新项目追求运维简单选 etcd(Go 单二进制,无需 JVM 调优)。


看到什么就先想到这类

关键词 / 场景优先想到
分布式系统设计取舍CAP 定理,先判断 CP 还是 AP
高可用 vs 强一致BASE 理论,最终一致性
配置中心 / 分布式锁ZooKeeper(CP)、etcd(Raft)
服务注册发现Eureka(AP)、Consul(CP)
多节点如何达成共识Raft(工程常用)、Paxos(理论基础)
Paxos 两阶段 / Proposer 抢占活锁Basic Paxos + Multi-Paxos(稳定 Leader 破活锁)
Paxos vs Raft 区别Raft = Multi-Paxos 工程化(强 Leader + 顺序日志)
etcd / TiKV 内部原理Raft 算法
ZooKeeper 内部原理ZAB 协议
缓存 / 存储分片路由一致性哈希 + 虚拟节点
节点增删数据迁移代价一致性哈希(vs 取模哈希)
数据倾斜 / 热点虚拟节点,增加哈希环分布均匀度
数据库事务 vs 分布式存储ACID vs BASE 对比
事件排序 / 因果关系 / 并发检测分布式时钟(Lamport/Vector/HLC)
K8s 元数据 / 云原生服务发现etcd(Raft)
临时节点 / 一次性 WatchZooKeeper(ZAB)
异步系统共识的理论极限FLP 不可能定理