ARC 2选择正确的一致性语义第 5–9 章
第 9 章 —— 从业务不变量选择集合
本章目标: 本章完成后,开发者能够从业务不变量出发,为 Register、Lease 或 CRDT 给出可反驳、可验证的选择理由。
学习目标
- 先判断状态是否适合 DSM,再选择集合。
- 把不变量映射到集合语义和失败边界。
- 为每个选择写出最小验证实验。
- 识别应该退回数据库或消息系统的状态。
前置条件
- 已完成第 5—8 章的三类集合实验。
- 能说出本地成功、远端可见和最终收敛的差异。
案例进度
团队对 route hint、shard owner 和 request counter 分别开展设计评审,逐项写出采用条件、失败行为和拒绝理由,不预设所有状态都进入 DSM。
决策顺序
第一问始终是:状态丢失后能否从同伴修复或从权威源重建?若不能,或一次局部成功会直接形成不可撤销业务承诺,就先保留在事务/事件事实源。
| 状态 | 关键不变量 | 选择 | 分区窗口 | 验证重点 |
|---|---|---|---|---|
| route hint | 一个 key 有当前可见提示 | Register | 两端可短暂不同 | 同 key 确定性收敛、陈旧回源 |
| shard owner | 有期限所有权,旧 owner 不能写 | Lease | 旧 holder 可能仍运行 | 转移后 fencing token 拒绝旧写 |
| request counter | 各节点可本地更新并安全合并 | CRDT | 局部计数短暂不完整 | 重复、乱序、分组合并结果不变 |
| order/payment | 事务事实与审计历史 | 不采用 DSM 主存储 | 双成功不可撤销 | 事务、幂等、对账、审计 |
选择是一个可检验假设
写「使用 Lease,因为它支持所有权」还不够。更完整的决策是:
对
orders-17,任一时刻只有持有最新 fencing token 的 worker 可提交调度结果;租约转移后,执行器拒绝旧 token。用转移测试和旧 token 反例验证。
这句话同时包含主体、状态、失败窗口、外部责任和证据。
反例与故障注入
- 用 Register 保存 shard owner:可以选出最新值,却没有 TTL/续租/转移/fencing 合同。
- 用 Lease 保存请求总数:强迫所有更新围绕唯一 owner,丢失本地可写优势。
- 用 CRDT 保存订单状态:可合并不等于合法状态迁移,也不提供跨资源事务和审计历史。
实验
打开 collection-review.json,为每个场景填写
decision、invariant、failureWindow
和 evidenceCommand。然后运行:
node --test tests/chapter-assets.test.mjs参考答案要求每个「采用」和「拒绝」都有业务理由,不能只填集合名称。
实验验收卡
| 字段 | 内容 |
|---|---|
| 运行命令 | node --test tests/chapter-assets.test.mjs |
| 输入或故障 | 7 个业务状态及其不可变量、失败窗口 |
| 可观察结果 | 三类 DSM 集合和拒绝项均被覆盖;字段完整 |
| 证据等级 | E1:设计评审资产检查,引用前章 E2/E3 实验 |
| 本实验未证明 | 新业务场景自动适配、生产容量或组织接受度 |
回顾
- 先决定 DSM 是否适合,再在三类集合之间选择。
- Register 解决当前值,Lease 解决有期限所有权,CRDT 解决可合并本地更新。
- 每个决定需要同时写出失败窗口与验证命令。
- 订单、库存和支付继续由事务事实源承担。
下一步
第 10 章进入第三篇:在讨论 delta 和 repair 前,先弄清谁在集群里、谁只是被怀疑离线。