关于 consistency-coordination
用于设计分布式数据一致性与协调的技能,面向需要为复制或分片节点选择保证级别的工程师。它比较一致性模型、节点协作方式、跨服务事务及键分布方案。
主要功能
- 01选择一致性模型
- 02比较主节点、法定人数与共识
- 03Saga 和分布式事务指引
- 04使用一致性哈希分配键
- 05分析网络分区与故障转移
适用场景
- 01为复制数据选择读取保证
- 02规划网络分区时的系统行为
- 03为主节点选举选择协调方式
- 04在弹性集群间分布键
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ proyecto26/ system-design-skills --skill consistency-coordination安装后在 Claude Code 中输入/consistency-coordination确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/deep-dive.mdreferences/providers/aws.mdgcp.mdgeneric.md详细介绍
一致性与协调
当数据分布在多个节点上时,确定读者能看到什么,以及各个独立节点如何对单一答案达成一致。处理不当,系统要么会悄无声息地提供过时或冲突的数据,要么会在网络链路中断时立刻停滞——这是分布式系统中最常见、代价最高的故障。
何时使用
只要状态需要在节点间复制、分片或协调,就会用到:选择复制或仲裁方案、选择一致性级别、选举领导者、在弹性集群中分布键( 一致性哈希),或提交跨服务的变更。一旦有人问“写入后立即读取会看到什么?”或“发生网络分区时会怎样?”,就该参考这里。
何时不使用
没有副本的单节点无需协调——不要为它引入仲裁或共识(YAGNI)。大多数应用可以容忍几秒钟的数据过时;如果最终一致性已经足够,却采用强一致性或分布式事务,只会带来延迟和运维负担,却无法获得任何需求明确要求的保证。满足不变量的最低成本方案才是最佳选择。在正确性要求迫使你这样做之前就提到 Raft 或 2PC,是个危险信号。
先明确需求
- 读取到过时数据会造成什么问题? 错误的余额与稍旧的点赞数,代表的是不同的系统。(→
requirements-scoping。) - 用户是否必须立即看到自己写入的数据? 读己之写的成本远低于全局强一致性。
- 网络分区或区域丢失的影响范围有多大? 这将决定 CAP/PACELC 取舍。(GUIDE 故障模式 #1。)
- 写入争用和冲突形态——每个键由单个写入者负责,还是需要解决并发写入者之间的冲突?
- 延迟预算——同步协调会增加一次往返(或一次跨区域往返);请确认预算能够承受。(→
back-of-the-envelope。)
可选方案
选择一致性模型(读取所获得的保证):
- 强一致性/线性一致性——每次读取都能看到最新的已提交写入。用于必须全局满足不变量的场景(余额、库存、唯一性)。
- 读己之写/单调一致性——会话能看到自己的写入,且读取结果不会倒退。用于个人资料编辑、“发布后立即看到自己的帖子”等场景。
- 因果一致性——读取遵循因果顺序(回复不会先于其父消息出现)。用于评论、聊天和协作编辑。
- 最终一致性——副本会“很快”收敛;读取可能滞后。用于点赞数、信息流、缓存等数据过时成本较低的场景。
选择副本达成一致的方式:
- 单领导者(主节点)——一个节点负责为所有写入排序;其他节点复制数据。适用于可以接受明确写入所有者的场景;这是常见的默认方案。
- 仲裁(R + W > N)——从多数节点读取/写入;根据工作负载调整 R 和 W。适用于需要可调一致性和可用性的无领导者存储。
- 共识(Raft / Paxos)——多数节点就复制日志达成一致,即使发生故障也能继续。用于控制平面:领导者选举、配置、元数据、锁。
协调跨多个键/服务的变更:
- Saga——一系列本地事务,并配有用于补偿的撤销操作。适用于无法使用全局锁的跨服务场景;接受最终一致性。
- 2PC/分布式事务——通过协调器,在多个节点间实现全有或全无的原子性。仅在原子性不可或缺且能够接受相应成本时使用。
在节点间分布键——一致性哈希(本技能涵盖):将键和节点映射到哈希环上;键归属于顺时针方向上的下一个节点。添加或移除节点时,只需重新映射约 K/N 个键,而不是几乎全部键(普通的 hash(key) % N 会导致这种情况),从而避免大规模重新映射。虚拟节点可均衡负载并抑制热点。这是缓存、无领导者存储和负载均衡后端的标准分区方案。具体机制见 references/deep-dive.md。
权衡
| 选项 | 解决的问题 | 带来的问题 | 何时更改 |
|---|---|---|---|
| 强一致性/线性一致性 | 正确性;无陈旧读取 | 延迟(一次往返/法定人数);分区时不可用(CP) | 可以容忍陈旧数据 → 放宽为读己之写/最终一致性 |
| 读己之写 | 无需付出全局代价即可“看到自己的更改” | 其他用户仍会看到陈旧数据;需要会话/粘性路由 | 出现全局不变量 → 改用强一致性 |
| 最终一致性 | 最高可用性 + 最低延迟(AP) | 读取到陈旧数据和冲突;需要冲突解决机制 | 不变量无法容忍分歧 → 使用更强的一致性模型 |
| 单主节点 | 顺序简单;无写入冲突 | 主节点是写入的单点故障;故障转移期间存在空档;从节点读取会滞后 | 写入吞吐量超出单个节点的能力,或主节点所在区域丢失 → 改用多主节点/法定人数 |
| 法定人数(R+W>N) | 可针对每次调用调节一致性与可用性 | 读写成本更高;并发写入仍需处理冲突 | 即使一次法定人数慢路径也代价过高 → 改用主节点或本地读取 |
| 共识(Raft/Paxos) | 节点丢失后仍能达成一致 | 需要多数节点(低于法定人数时会失去可用性);写入延迟;复杂 | 数据平面需要在大规模下实现共识 → 将协调工作交给服务 |
| Saga | 无需全局锁即可实现跨服务更改 | 无隔离性;部分状态可见;必须设计补偿操作 | 需要真正的原子性 → 使用 2PC(并接受其成本) |
| 2PC | 多节点原子提交 | 协调器是单点故障;投票期间会持有锁;故障时会阻塞 | 可用性/吞吐量比严格原子性更重要 → 改用 Saga |
压力下的行为
本部分的全部目的在于说明故障场景——网络或节点出故障时会发生什么(GUIDE #1、#6)。
- 网络分区是迫使系统做出选择的因素(CAP 中 C 与 A 的取舍)。CP/强一致性系统会在少数派一侧拒绝写入,以保护不变量——以牺牲可用性换取正确性。AP/最终一致性系统会在所有地方接受写入,之后再进行协调——以牺牲正确性换取可用性。说明你选择了哪一种以及原因;没有第三种方案能同时保留二者。
- 主节点丢失会触发选举。在此期间,写入会暂停(单主节点),或带风险地继续(如果允许过期主节点继续写入 → 脑裂,导致历史记录分歧)。隔离令牌和多数派法定人数可防止出现两个主节点。
- 法定人数低于多数派(停机节点过多)意味着严格的法定人数存储会按设计停止接受写入。停机节点数超过
N − W会阻止写入;超过N − R会阻止读取。 - **协调会放大故障:**2PC 协调器崩溃会导致参与者持有锁(造成阻塞);丢失法定人数的共识集群会冻结控制平面以及依赖它的一切。过于激进的主节点选举超时可能引发选举风暴(负载下反复重新选举)。
- **监控:**复制延迟(陈旧数据窗口)、主节点选举频率和持续时间、法定人数健康状况(可访问节点数与 N 的对比)、冲突/修复频率,以及对于一致性哈希,每个节点的键分布和再平衡量。
故障转移的权衡(主动-被动与主动-主动、数据丢失窗口)由 resilience-failure 介绍;本部分说明每种方案的一致性代价。
如何应用
- 明确不变量。 弄清楚陈旧读取或冲突读取会导致什么问题、用户是否必须看到自己的写入,以及分区的影响范围(使用“先澄清”问题)。没有不变量 → 默认采用最终一致性,并到此为止。
- 从权衡表中选择模型和一致性方案: 让保证满足数据所能容忍的最弱不变量,然后根据写入由谁负责以及必须承受何种节点丢失,选择单主、多数派或共识。只有当变更跨越多个服务且必须保证原子性时,才加入 saga 或 2PC。
- 设置参数。 按操作(而非按数据存储)指定一致性级别;在需要重叠的地方设置
N、R、W,使R + W > N;选择冲突处理策略(LWW / version-vector / app resolver);当集群规模会变化时,使用一致性哈希来分配键。 - 对选择进行压力测试。 明确说明 CAP 取舍:发生分区、主节点丢失以及节点数低于法定人数时会怎样。确认已隔离脑裂,并且协调机制不会将一次故障扩大为整个集群冻结。
- 用数字估算规模。 通过
back-of-the-envelope,将协调往返开销(同一数据中心与跨区域)与延迟预算进行比较,并根据故障目标确定N。如果强一致性超出预算,就放宽模型。 - 映射到云服务提供商。 默认采用通用方案;如果指定了云服务提供商,则查阅其对应文件,了解托管式一致性参数和法定人数存储限制。
- 在答案中展示权衡 — 提供一张
Decision | Solves | Worsens | Change it when…表格,每个所选方案占一行(例如选项、存储、故障策略);最后一列给出具体触发条件(数字或可观测信号)。然后指出最先出问题的环节。
应做与不应做
应做
- 按操作指定保证 — 大多数读取采用最终一致性,只有涉及不变量的操作才采用强一致性 — 这样只在有助于保证正确性的地方付出协调成本。
- 明确说明 CAP 取舍:发生分区时,指出哪一侧拒绝写入(CP),哪一侧接受写入并进行协调(AP)。不存在兼顾两者的选项。
- 根据重叠要求和故障目标设置
R、W、N,并通过多数派法定人数和隔离令牌对主节点进行隔离。 - 返回版本号(或向量时钟),以便调用方检测并解决冲突。
不应做
- 不要在不变量提出要求之前就采用强一致性、共识或 2PC — 陈旧数据通常代价不高,而全局协调会增加延迟和负担。
- 不要在写入预算紧张时,跨区域运行同步强一致性或 2PC;一次跨区域往返就可能增加 100 ms 以上延迟。
- 不要让陈旧主节点在选举间隙继续写入 — 这会造成脑裂。
- 不要使用
hash(key) % N对键分片;成员变更时,这会导致几乎所有键都重新映射,而非约K/N个键。
重要数字
协调成本主要取决于往返次数,而非 CPU。数据中心内的往返耗时不到 1 毫秒;跨区域往返耗时为数十毫秒至约 100 毫秒以上 — 因此,跨区域执行同步强一致性或 2PC,每次写入可能增加 100 毫秒以上延迟。法定人数大小为 ⌊N/2⌋ + 1;当 N=3 时,必须有两个节点达成一致,因此集群可承受一个节点故障。一致性哈希在成员变更时只会重新映射约 K/N 个键(而取模会影响几乎所有键)。使用 back-of-the-envelope 中的延迟表和可用性“9”位数计算,估算往返开销,并根据故障目标确定 N。
接口示意
契约是保证,需要针对每项操作明确说明,并列出实现该保证所需的参数:
ConsistencyLevel: STRONG | READ_YOUR_WRITES | CAUSAL | EVENTUAL
Quorum: N (replicas), W (write acks), R (read acks) // R + W > N ⇒ overlap
Write API: write(key, value, level=STRONG) -> {version|vector_clock}
Read API: read(key, level=EVENTUAL) -> {value, version, stale?: bool}
Conflict policy: last-write-wins(ts) | version-vector-merge | app-resolver
按操作而非数据存储指定级别 — 大多数读取可以采用最终一致性,而少数涉及不变量的读取需要强一致性。返回版本号,以便调用方检测并解决冲突。
选择提供商
默认使用上面的通用方案。如果用户指定了云服务,请阅读
references/providers/<provider>.md,了解托管服务映射、
配额/限制和提供商特有的权衡。如果该提供商没有对应文件,则使用通用方案。
图示
要直观展示主从分区场景、法定人数读写或一致性哈希环,请使用插件内的 architecture-diagram 技能。快速推理时,可以使用内联示意图(client → leader → [replication stream] → followers,分区用虚线/断裂箭头表示);不要嵌入 Mermaid。
相关构建模块
data-storage— 与此模块配合使用:它负责复制和分片/分区(具体机制),此模块提供这些机制所实现的一致性保证。messaging-streaming— 是在数据平面中协调的替代方案:消息排序和恰好一次传递在传输层上是同一个问题;当事件必须排序或去重时,可与此模块配合使用。resilience-failure— 为此模块提供支持:它负责故障转移、重试和优雅降级;此模块则为它提供的可用性机制所付出的一致性代价定价。caching— 依赖于一致性哈希(这一自有概念位于该模块中)来对分布式缓存进行分片,并以新鲜度换取速度。back-of-the-envelope— 相关自有概念位于该模块中:用于评估往返开销和确定N大小的延迟表与可用性 9 的个数计算。service-decomposition— 跨服务一致性(saga/2PC)以及服务发现背后的协调机制(领导者选举、etcd/Consul/ZooKeeper)依赖于此模块。system-design— 当设计涉及状态复制或协调时,会将请求路由到此处的编排器。
参考资料
references/deep-dive.md— 全面介绍 CAP 与 PACELC、一致性模型机制、法定人数计算、高层次的 Raft/Paxos、领导者选举与脑裂(隔离令牌)、一致性哈希环与虚拟节点,以及 2PC 与 saga 的内部机制。设计协调层时,可详细阅读。references/providers/{generic,aws,gcp}.md— 各环境中的协调服务(ZooKeeper/etcd/Consul)、法定人数存储,以及托管一致性配置项(例如 Spanner 外部一致性、DynamoDB 一致性读取标志)。