distributed-systems.md 6.6 KB

分布式系统设计

本 reference 是分布式系统设计专项,覆盖跨服务/跨机器/跨数据库场景的一致性、事务、幂等与协调问题。与 code-generation 的 NFR 决策(并发/竞态维度)互补——NFR 决策覆盖单机并发,本 reference 覆盖分布式并发与跨服务一致性。

适用边界

  • 加载:多服务协作/跨数据库事务/消息驱动/分布式锁/事件驱动架构
  • 跳过:单机单库 CRUD(直接 code-generation + mysql-database);无跨服务一致性问题(避免过度设计,呼应 Karpathy 简洁优先)

核心概念速查

| 概念 | 定义 | 关键决策 | | - | - | - | | CAP 定理 | 一致性/可用性/分区容忍三角,分布式系统最多同时满足两个 | 多数业务选 AP + 最终一致;金融强一致选 CP | | 分布式事务 | 跨服务/跨库数据一致性保证 | 2PC(强一致/阻塞)/TCC(业务侵入)/Saga(补偿)/本地消息表(最终一致) | | 最终一致性 | 接受短暂不一致,通过异步达成一致 | 事件驱动/CDC/定时对账 | | 幂等 | 重复调用不产生副作用 | 幂等键/唯一约束/去重表/状态机 | | 分布式锁 | 跨进程互斥协调 | Redis(性能优先)/Zookeeper(可靠优先)/数据库锁(简单优先) |

执行流程

第一步:识别分布式场景

判断是否命中分布式特征:

  • 跨服务调用(订单服务 → 库存服务 → 支付服务)
  • 跨数据库/跨表分库
  • 消息驱动(MQ/事件总线)
  • 多实例并发写同一资源

无上述特征 → 退出本 reference,走单机方案。

第二步:CAP 选择

| 业务特征 | 选择 | 理由 | | - | - | - | | 金融/库存/账户余额 | CP(强一致) | 不一致直接造成资金损失 | | 内容/社交/搜索索引 | AP(最终一致) | 短暂不一致可接受,可用性优先 | | 订单状态流转 | 混合(关键状态CP,非关键AP) | 按业务粒度分级 |

第三步:事务模式选择

| 模式 | 一致性 | 代价 | 适用场景 | | - | - | - | - | | 2PC | 强一致 | 阻塞/性能差/协调者单点 | 同库跨表、少量跨库 | | TCC | 强一致 | 业务侵入大(Try/Confirm/Cancel三接口) | 资金/库存需强一致 | | Saga | 最终一致 | 补偿逻辑复杂 | 长流程业务编排 | | 本地消息表 | 最终一致 | 需消息可靠投递+消费幂等 | 异步解耦场景 |

选择须走 architecture-decision 产出决策记录,含反选论证。

第四步:幂等设计

所有写操作必须幂等(网络重试不可避免):

  • 幂等键:业务唯一标识(订单号+操作类型)作为幂等键
  • 唯一约束:数据库唯一索引兜底重复写入
  • 状态机:状态流转只允许前进,重复请求命中终态直接返回
  • 去重表:处理前查去重表,处理完写入

第五步:补偿与回滚

  • Saga 补偿:每步正向操作必须有对应补偿操作
  • 补偿幂等:补偿本身可重入(补偿可能失败重试)
  • 重试策略:指数退避 + 最大次数 + 死信队列
  • 人工介入:死信队列消息转人工处理,不静默丢弃

第六步:可观测性

  • 分布式追踪:TraceId 贯穿调用链
  • 幂等日志:记录幂等键命中/miss
  • 对账机制:最终一致性场景必须有定时对账,发现不一致告警

第七步:验证与沉淀

  • 并发/重复/乱序/部分失败场景测试(联动 test-generation)
  • 分布式决策记录沉淀到项目记忆(联动 project-memory-management)

架构规则

  1. 跨服务事务必须显式选择模式,禁止隐式假设"会成功"
  2. 写操作必须幂等(网络重试不可避免)
  3. 最终一致性必须给对账机制,不能"发了事件就不管"
  4. 分布式锁必须设超时 + 持有者标识,禁死锁
  5. 补偿必须可重入(补偿本身可能失败重试)
  6. 禁跨服务大事务,拆为本地事务 + 事件
  7. 事件必须有序或可容忍乱序,消费端必须幂等

常见坑

| 坑 | 后果 | 规避 | | - | - | - | | 跨服务用数据库事务 | 2PC 阻塞/性能差/不可用 | 用 Saga 或本地消息表 | | 忘幂等 | 重试导致重复扣款/重复下单 | 幂等键 + 唯一约束 | | 事件丢了不感知 | 数据不一致无告警 | 事件存储 + 对账机制 | | 分布式锁不设超时 | 持有者崩溃 → 死锁 | 超时 + 持有者标识 + 看门狗续期 | | 补偿不可重入 | 补偿失败 → 数据卡住 | 补偿幂等 + 重试 + 死信队列 | | 跨服务大事务 | 锁竞争/超时/雪崩 | 拆本地事务 + 事件解耦 | | 事件乱序未处理 | 状态错乱(如先取消后支付) | 版本号/时间戳/状态机守卫 |

关联 reference

| 协同点 | 说明 | | - | - | | code-generation | NFR 决策的分布式维度补充;生成代码须体现幂等/补偿/锁超时 | | architecture-decision | 事务模式/一致性模型/CAP 选择走架构决策流程,附反选论证 | | mysql-database | 本地事务边界、数据库锁、唯一约束兜底 | | api-design | 幂等接口设计、重试语义、Init-Step-Poll 长任务契约 | | test-generation | 分布式场景测试(并发/乱序/重复/部分失败) | | code-review | 审查幂等缺失/补偿不可重入/锁无超时/事件无对账 | | domain-driven-design | 跨聚合最终一致性、领域事件驱动、限界上下文间映射 | | project-memory-management | 分布式事务模式/CAP 选择决策记录沉淀 |

质量标准

  • 事务模式选择必须基于 CAP 权衡,不能默认"强一致"
  • 幂等必须覆盖所有写操作,不能"部分幂等"
  • 补偿必须可重入,不能"补偿一次就废"
  • 最终一致性必须给对账,不能"发了就不管"
  • 分布式锁必须防死锁(超时 + 持有者 + 续期)
  • 适用边界外的简单场景不得强加分布式模式(呼应 Karpathy 简洁优先)

失败回退机制

| 步骤 | 失败条件 | 回退目标 | 最大重试 | 不可恢复时升级路径 | | - | - | - | - | - | | 第二步:CAP 选择 | 业务无法接受任何不一致 | 走 architecture-decision 评估 2PC 代价 | 0 | 交用户拍板 | | 第三步:事务模式 | Saga 补偿逻辑复杂无法实现 | 降级为本地消息表 + 最终一致 | 1 | 标注限制,部分强一致部分最终一致 | | 第四步:幂等设计 | 无自然幂等键 | 用业务唯一标识或生成 UUID 幂等键 | 1 | 咨询业务方确认唯一标识 | | 第五步:补偿设计 | 补偿无法幂等 | 死信队列 + 人工介入 | 0 | 标注需人工对账,不自动重试 | | 第六步:可观测性 | 无追踪/对账基础设施 | 输出需补建的基础设施清单 | 1 | 标注"可观测性不足",建议后续补建 |