ARC 6证明边界并完成毕业项目第 23–26 章
第 25 章 —— 识别不适合 DSM 的状态
本章目标: 本章完成后,开发者能够从业务不变量、失败后果和证据要求反选技术,不因低延迟、分布式或「共享」三个词默认选择 DSM。
学习目标
- 先判断状态是否可修复,再讨论集合类型。
- 区分事实源、缓存、历史日志、共识协调与 DSM。
- 为采用或拒绝 DSM 写出可审查理由。
- 识别双写、无限状态和不可观测修复三类反模式。
前置条件
- 已完成三类集合、分区边界、容量和 federation。
- 能写出状态丢失、重复、乱序和分歧的业务后果。
- 愿意把「不用 DSM」视为成功的设计结论。
案例进度
履约团队重新评审订单、库存扣减、route hint、shard owner、request counter 和审计事件。评审目标是确认每种状态的正确责任边界,不以扩大 DSM 覆盖范围为成果。
先反选,再选集合
| 需求 | 首选责任 | 为什么不是 DSM 的主责任 |
|---|---|---|
| 订单、余额、库存扣减等权威事实 | 事务数据库或事实服务 | 已确认事务不能被最终收敛重写 |
| 完整、可重放的发生历史 | 事件日志或流平台 | DSM 以当前协同状态为中心,不承诺完整历史 |
| 跨节点线性化配置、选主或强 CAS | 共识协调服务 | DSM 分区下可能允许局部成功 |
| 只需低延迟读且可从事实源重建 | 缓存 | 不需要引入领域合并、repair 与协议身份 |
| 小规模、可修复、领域语义明确的协同状态 | DSM 候选 | 可用 Register、Lease、CRDT 表达不变量 |
「候选」还不是批准。仍需回答状态规模、TTL/清理、schema 演进、失败可观测性、repair 成本、安全、容量和团队运维能力。
三个应当直接拒绝的信号
- 把 DSM 和数据库都当 writer:没有单一权威和补偿协议的双写,只会制造另一层分歧。
- 状态无界增长:把完整订单历史、日志或分析明细塞进内存集合,生命周期与容量不可控。
- 无法解释失败窗口:只说 eventual consistency,却说不出两个 OK、旧 token、丢 delta 或慢消费者的业务处理。
贯穿案例的最终边界
route-hints:Register 候选;事实来源仍是健康检查/服务管理系统。shard-owners:Lease 候选;外部写入需要校验 fencing token。request-counter:PN-Counter 候选;用于可合并观测,不用于财务结算。- 订单与库存:拒绝 DSM 作为事实源。
- 审计事件:进入不可变历史系统,不能只依赖 ChangeStream。
反例与故障注入
- 把库存余额改为 Register,并制造分区双写;说明收敛后的 winner 仍会丢失业务扣减。
- 把 ChangeStream 当审计日志,触发 overflow;指出观察事件可丢与历史完整性的冲突。
- 把 CRDT counter 当账单金额,说明重复来源、撤销和法律记录无法由局部 merge 自动解决。
- 为纯缓存数据增加自定义 resolver,比较它与从事实源重建的复杂度。
实验
npm test -- --test-name-pattern="phase 6 assets"在 technology-selection-review.json 中对八类状态逐项写出
invariant、failure cost、source of truth、选择与反证条件。
实验验收卡
| 字段 | 内容 |
|---|---|
| 运行命令 | 书籍静态决策资产测试 |
| 输入或故障 | 事实、历史、强协调、缓存、可修复协同状态 |
| 可观察结果 | 每项都有采用/拒绝理由和改变决定的反事实条件 |
| 证据等级 | E1:设计评审;需与目标系统运行证据结合 |
| 本实验未证明 | 某个替代产品已经满足 SLA、安全、成本或团队能力 |
回顾
- 先问失败是否可修复,再问用哪种集合。
- DSM 不拥有订单事实、完整历史或全局线性化承诺。
- 可从事实源重建的低延迟读取问题通常先按缓存需求评估,不能仅因涉及多个实例就引入一致性框架。
- 拒绝 DSM 需要像采用一样给出可复核理由。
下一步
第 26 章把全书方法收敛成一个可运行、可故障注入、可观察且边界诚实的毕业项目。