跳到主要内容
约 5 分钟3 张卡

一致性模型

一致性模型规定并发操作允许观察到的结果。本文讲解线性、顺序、因果和会话保证,并分析 Quorum。

1. 面试核心​

先记住这几条,再读正文
  • 线性一致性。 线性一致性让每次操作原子生效,并保留非重叠操作的实时顺序。
  • 顺序一致性。 顺序一致性保留全局排列和客户端程序顺序,弱化跨客户端实时要求。
  • 因果与会话保证。 因果一致性保留依赖顺序,会话保证约束单个会话的观察。
  • Quorum 交集。 W+R>N 保证固定副本集合的读写交集,协议还需约束版本。卡 · 线性一致性
  • 事务隔离。 可串行化约束整个事务,严格可串行化再加入实时顺序。卡 · 可串行化与原子操作

2. 线性一致性​

每次操作可视为在调用与返回之间某刻生效。若写已返回,之后开始的读需看到该写或更新结果。重叠操作可按任一符合对象语义的顺序排列。

线性一致适合锁、配置和唯一所有权等协调状态。多个独立操作仍有各自的生效点。

2.1 可串行化与原子操作​

可串行化要求事务效果等价于某种串行执行。事务可以包含多个对象的读写。严格可串行化再要求该顺序尊重实时先后。

单次读和写都线性一致,也会发生先读后写竞态。例如,A、B 都读到计数 0,再各自写入 1。所有调用都可合法排序,但两次加一只得到 1。

原子 increment、CAS 重试或可串行化事务可保护整体动作。需要什么保证,取决于操作的边界。

3. 顺序一致性​

全部操作可以排成共同顺序。该顺序保留每个客户端的程序顺序。不同客户端之间的实时先后则可被重排。

因此,另一个客户端稍后发起的读,可以排在已返回的写之前。需要实时协调时,应选择更明确的线性一致语义。

4. 因果一致性​

若回复依赖原帖,观察回复时应已能观察原帖。彼此无依赖的并发更新可在不同副本上按不同顺序出现。

版本向量和因果上下文可跟踪依赖。并发版本仍需合并规则。

5. 会话保证​

单个会话可获得以下保证:

  • 读己之写让用户读到自己已经完成的更新。
  • 单调读让后续读取保持或推进版本。
  • 单调写保留会话内的写入顺序。
  • 写随读保留读取内容对后续写入的因果依赖。

会话版本 token 可要求目标副本追平。粘性副本也需在切换时传递进度。仅固定地址不足以覆盖副本故障。

6. 最终一致性​

停止更新且传播恢复后,可用副本最终收敛。该定义没有固定的收敛时限。工程上还需设置传播目标与监控。

LWW 可丢弃并发更新中的一个版本。计数或集合可选择适合的可合并结构。收敛结果是否符合业务规则,需要单独验证。

7. Quorum​

设固定副本集合大小为 N,写等待 W 个副本,读查询 R 个副本。满足 W+R>N 时,读集合与已确认写集合相交。W>N/2 则让两个写集合相交。

交集提供信息来源。读协议仍需选择版本,并处理部分成功的写入。线性一致实现可以有 Leader,也可以采用无主原子寄存器协议。

7.1 部分写入与读回退​

假设 N=3,W=2,R=2,初值为 0。写入 1 只到 A,写请求尚未完成。读请求一查询 A、B,并返回最大版本 1。随后读请求二查询 B、C,却返回 0。

两次读都满足 R=2,但观察发生回退。若第一次读把未完成写视为已经生效,第二次就应保留该结果。

原子寄存器协议可通过读回写等机制保护观察结果。sloppy quorum 则会借用固定集合之外的节点。它连固定集合的交集前提也会改变。

8. Leader 的领导权确认​

旧 Leader 在失联后仍会认为自己有效。线性读取需要新的领导权证据,并等待状态机应用到安全位置。具体读屏障见Raft。

异步副本可提供陈旧读。只等待一个历史提交位置,可提供对应的会话保证。要线性读取,还需获取本次读的安全依据。

9. CAP 与一致性​

分区下同时保证线性一致与全节点可用受到CAP 理论约束。事务业务约束与副本观察语义应分别描述。

10. 常见问题​

10.1 强一致的具体含义​

“强一致”需落实为具体保证。线性一致、可串行化、同步复制和读己之写各有边界。设计文档应说明实际允许的操作历史。

10.2 多数读取与版本选择​

11 · 面试题卡片​

11.1 Quorum 的 W + R > N 为什么仍不能单独证明线性一致​

出现公司:字节跳动、百度、美团、滴滴

考察重点

  • 线性、顺序、因果、会话与最终一致。
  • Quorum 交集、版本选择和结果未知。
  • Leader 任期、读确认和 CAP 分区选择。

相关内容:线性一致性至CAP 与一致性。

参考回答

W+R>N 只保证固定副本集合中读写相交,线性一致性还要求协议正确处理版本、并发和未完成写入。

例如,新值只写到 A 时,第一次读 A、B 选出新值,第二次读 B、C 却返回旧值,就发生读回退。

协议需让整段操作历史符合实时顺序,并约束读确认和成员变化。Leader、读回写等经过证明的协议可实现这些约束,仅有 W、R、N 三个数字还不够。

11.2 每次读写都线性一致,为什么两个客户端加一仍会丢更新?​

出现公司:暂无已核验的公开来源(本站自测)

考察重点:操作边界、CAS 与事务可串行化。

相关内容:可串行化与原子操作。

参考回答

读和写是两个独立操作,整体加一并未原子化。

两个客户端都读到 0,再各自写入 1,符合单次调用的线性一致性。整体加一需用原子 increment、CAS 重试或合适的事务隔离。

11.3 W=2、R=2、N=3 时,部分写入怎样造成连续读取回退?​

出现公司:暂无已核验的公开来源(本站自测)

考察重点:未完成写、读回写与交集前提。

相关内容:部分写入与读回退。

参考回答

写入 1 只到 A 时,读 A、B 可选出 1。

稍后读 B、C 仍会得到 0。交集 B 没有新值,无法保留前一次观察。安全协议需处理这种未完成写,例如在返回前读回写到法定集合。

12. 参考资料​