目录
正在加载目录…
专栏文章
专栏文章
决策与权衡专栏
1. 决策与权衡总览:从选项到可审阅的承诺 2. 决策记录ADR:让技术决策可追溯可演进 3. 决策矩阵与权衡:在多目标下显式取舍 4. 可逆性与双向门:降低决策的不可逆成本 5. Premortem与预承诺:在行动前发现失败路径 6. 决策与权衡综合实践:做一次可复盘的技术选型 7. 附录:ADR 模板与示例

附录:ADR 模板与示例

发布于 2026-08-25 11:08 · 最后编辑于 2026-08-25 11:08 · 字数 1,520 👁 0 次阅读

TL;DR:本篇提供 ADR(架构决策记录)的空白模板与一个公认写得好的完整示例。模板遵循 Michael Nygard 的原始四要素结构,示例改编自业界广泛参考的微服务缓存决策案例。直接复制模板使用,对照示例检查完整度——一篇合格的 ADR 不在于篇幅,而在于假设可证伪、后果含负向、放弃了什么被写明

概念解释

ADR 模板的来源

Michael Nygard 在 2011 年的文章《Documenting Architecture Decisions》中提出的格式极其简洁:Context(上下文)、Decision(决策)、Consequences(后果)。社区后续扩展出多种变体(MADR、Y-Statements),但 Nygard 原版因其极低的上手成本,仍是业界最广泛使用的格式。本模板在原版基础上增加**假设(Assumptions)**字段——这是本专栏的核心深化,因为假设是触发重新决策的钩子。

怎样算一篇写得好的 ADR

维度好的 ADR差的 ADR
上下文写明面临的约束、团队现状、业务量级只写"需要选一个缓存"
决策写明选了什么、放弃了什么只写"选 Redis"
后果正向和负向都写只写优点
假设可证伪,有触发重评的信号无假设或假设藏在脑里
篇幅1-2 页10 页文档或半句话

目录

章节说明
ADR 空白模板直接复制使用
完整示例:缓存方案选型公认写得好的参考案例
模板变体说明MADR、Y-Statements 简介
使用建议何时写、放哪、怎么演进

ADR 空白模板

# ADR-{编号}: {决策标题}

**状态**: Proposed | Accepted | Deprecated | Superseded by ADR-{编号}
**日期**: YYYY-MM-DD
**决策者**: {负责人}

## 上下文

{面临的工程问题、约束、团队现状、业务量级、时间尺度。
  回答:为什么现在需要做这个决策?有什么不可妥协的约束?}

## 决策

{选定方案。一句话说清选了什么。
  补充:放弃了哪些候选方案?各自放弃了什么?}

## 后果

### 正向

- {选这个方案带来的好处}

### 负向

- {选这个方案带来的代价、风险、技术债}

## 假设

| 假设 | 可证伪信号(出现时重评) |
|------|--------------------------|
| {前提1} | {若观察到X则假设不成立} |
| {前提2} | {若观察到Y则假设不成立} |

## 退出条件

| 信号 | 预设行动 |
|------|----------|
| {可观察的阈值} | {触发后做什么} |

完整示例:缓存方案选型

以下是一个公认写得好的 ADR 示例,改编自微服务缓存选型的常见工程场景。

# ADR-007: 订单服务选用 Redis 主从版作为缓存

**状态**: Accepted
**日期**: 2026-01-15
**决策者**: 订单服务团队

## 上下文

订单服务 QPS 峰值 5w,读多写少(读写比约 10:1)。
当前使用本地缓存(Caffeine),存在以下问题:
1. 多实例间缓存不一致,导致超卖风险
2. 实例重启后缓存击穿,回源 DB 压力骤增
3. 无法支持跨实例的缓存预热

团队有 Redis 运维经验(哨兵模式),但无 Cluster 运维经验。
预算约束:年缓存成本不超过 X 万。
时间约束:需在 Q2 前完成迁移。

## 决策

选用 Redis 主从版(Sentinel 高可用),非 Cluster。
读穿透使用布隆过滤防止缓存穿透。

放弃的候选方案:
- Redis Cluster:团队无运维经验,迁移风险高,Q2 前无法稳妥上线
- Memcached:无持久化,重启后需全量预热,与超卖风险场景冲突
- 继续用本地缓存:多实例不一致问题无法解决

## 后果

### 正向

- 多实例缓存一致,消除超卖风险
- 哨兵自动故障切换,减少人工介入
- 团队已有哨兵运维经验,上手快

### 负向

- 单点写入瓶颈:写入 QPS 上限约 10w,若业务增长超 3 倍需迁移 Cluster
- 内存成本:预估 2 年内数据量约 50G,需预留 70% 水位
- 增加了一个运维组件,故障域扩大

## 假设

| 假设 | 可证伪信号 |
|------|------------|
| 订单数据量两年内不超 50G | Redis used_memory 超过 35G(70% 水位)|
| QPS 增长不超 3 倍(峰值不超 15w)| 单日峰值 QPS 连续 7 天超过 12w |
| 团队能在一个月内掌握哨兵运维 | 上线后哨兵切换失败率超过 1% |

## 退出条件

| 信号 | 预设行动 |
|------|----------|
| used_memory 超过 35G | 启动迁移 Cluster 评估 |
| 写入 QPS 峰值超 12w | 评估分片或迁移 Cluster |
| 哨兵切换连续失败 2 次 | 回退本地缓存 + DB 兜底,排查哨兵配置 |

模板变体说明

变体特点适用场景
Nygard 原版上下文 + 决策 + 后果(3 要素)快速上手、轻量记录
本专栏扩展版+ 假设 + 退出条件(5 要素)高影响或不可逆决策
MADR+ 多属性评分(加权矩阵集成)多方案竞争、需量化比较
Y-StatementsWhy/What/How 三段式架构全景梳理

建议:日常用 Nygard 原版或本专栏扩展版;高影响决策(数据库迁移、公开 API 契约)必须加假设和退出条件。

使用建议

何时写

  • 必须写:单向门决策(不可逆)、影响多个团队的决策、公开 API 契约
  • 建议写:技术选型、架构变更、数据迁移
  • 不必写:低风险可逆决策(如函数命名、内部工具选型)

放在哪

  • 放在代码仓库(推荐):随 git 历史可追溯,代码 review 流程天然覆盖决策评审
  • 不放 Wiki/Confluence:会因迁移丢失,且与代码脱节

怎么演进

  • 新决策推翻旧决策时,不删除旧 ADR,新建 ADR 并标注 Supersedes ADR-XXX
  • 旧 ADR 顶部标注 Superseded by ADR-YYY
  • 形成决策树,而非一堆孤立文件

练习

选一个你所在系统的技术决策,用本模板写一份 ADR。重点检查:假设是否可证伪?后果是否包含负向影响?放弃了哪些候选方案是否写明?若找不到当初的上下文,就把"现在能推断的"写明并标注"上下文为事后重建"。

关联笔记

参考资料

← 返回列表

评论 (0)

暂无评论,来留下第一条吧。
登录注册 后才能发表评论