架构决策方法:如何用 ADR 记录每一次取舍
上一篇文章中写了《架构师到底在做什么:从需求到上线的全链路责任》,这一篇讨论怎么记录架构决策。
架构设计中最容易丢失的,往往不是最终方案,而是决策过程。
记忆随着时间的推移是会模糊的,比如,半年后回看一个系统,大家通常只记得“我们用了 Kafka”“我们拆了微服务”“我们选了 Redis”,但很少有人能回答:
- 当时为什么选它?
- 有没有考虑过其他方案?
- 放弃了什么?
- 付出了什么代价?
- 这个决策现在是否还成立?
如果没有记录,架构就会逐渐变成一堆“历史遗留决定”。ADR 就是为了解决这个问题。
一、什么是 ADR
ADR 全称Architecture Decision Record,即架构决策记录。
它不是详细设计文档,也不是需求文档,而是一份轻量、可追溯的决策快照,用来回答一个问题:
在某个时间点,我们为什么做出了这个架构选择?
一份合格的 ADR 应该让新加入的团队成员在十分钟内理解:当时发生了什么、为什么这样选、现在还能不能改。
二、为什么架构师必须写 ADR
很多团队的问题不是没有决策,而是决策只存在于会议纪要、聊天记录或某个人的脑子里。
时间一长,会出现三种典型问题:
-
新人看不懂现状
看到一堆奇怪的配置、冗余的模块、过时的中间件,却不知道当初为什么存在。 -
重复讨论旧决策
每次有人提出“要不要换成 X”,都要重新把半年前的争论再走一遍。 -
架构腐化无人负责
系统逐渐偏离最初设计,但没有人能说清楚是从哪一步开始偏离的。
ADR 的价值在于:把架构决策从“拍脑袋”变成可复盘的工程资产。
三、ADR 应该包含哪些内容
一份实用的 ADR 不必复杂,但至少要包含以下要素:
| 字段 | 说明 |
|---|---|
| 编号 | 如 ADR-001,便于引用 |
| 标题 | 一句话概括决策内容 |
| 状态 | Proposed / Accepted / Deprecated / Superseded |
| 决策者 | 谁最终拍板 |
| 日期 | 决策发生的时间 |
| 背景 | 当时面临什么问题、有哪些约束 |
| 候选方案 | 列出至少两个可选方案 |
| 决策结果 | 最终选择了什么 |
| 决策理由 | 为什么选它,不选其他 |
| 代价与风险 | 这个选择带来了什么副作用 |
| 重新评估条件 | 什么情况下需要推翻这个决策 |
其中最重要的是:候选方案、决策理由、代价与风险。
只写“我们选了 Kafka”没有意义;写清楚“为什么没选 RabbitMQ / RocketMQ”才有价值。
四、一个 ADR 示例
ADR-001:设备上报通道选用 MQTT + Kafka
状态:Accepted
决策者:系统架构师
日期:20XX-XX-XX
背景
系统需要接入大量铁路信号设备上报数据,预计峰值 4 万点/秒。设备通过弱网环境连接,存在断线、重连、乱序、丢包等情况。后端需要保证数据不丢失、可重放,并支持后续流式处理。
候选方案
| 方案 | 优点 | 缺点 |
|---|---|---|
| HTTP 直连后端 | 实现简单,团队熟悉 | 弱网下重连成本高,推送能力弱,设备端负担重 |
| MQTT + RabbitMQ | 设备接入成熟,运维相对简单 | 高吞吐场景下持久化消息能力弱,重放能力有限 |
| MQTT + Kafka | 高吞吐、可重放、适合流式处理 | 运维复杂度较高,Kafka 资源占用更大 |
| TCP 长连接自研协议 | 完全可控 | 开发成本高,稳定性风险大,不利于后续扩展 |
决策结果
选用MQTT + Kafka作为设备数据上报通道。
设备端通过 MQTT Broker 接入,Broker 将消息转发至 Kafka Topic,后端消费 Kafka 进行清洗、存储和流式计算。
决策理由
-
设备接入层需要弱网友好
MQTT 的 QoS、Last Will、断线重连机制更适合工业现场环境。 -
后端需要高吞吐与可重放
Kafka 的顺序写入和分区模型能够支撑 4 万点/秒的写入压力,并且支持消息重放,便于数据回溯和故障恢复。 -
后续流式处理能力更强
Kafka 可以与 Flink、Spark Streaming 等流处理框架自然衔接,适合后续做实时告警、趋势分析和容量预测。 -
团队具备中间件运维基础
虽然 Kafka 运维复杂度高于 RabbitMQ,但团队已有容器化部署和监控经验,风险可控。
代价与风险
- Kafka 集群运维成本高于 RabbitMQ;
- 需要额外建设监控、告警和容量规划;
- 初期小规模场景下可能显得“过重”;
- 设备端需要适配 MQTT 协议,存量设备需通过网关转换。
重新评估条件
当出现以下情况时,应重新评估该决策:
- 设备规模长期低于 5000 点/秒,且无流式处理需求;
- 团队无法承担 Kafka 运维成本;
- 业务转向强事务、低延迟命令下发,而非高吞吐数据上报;
- 出现更合适的云托管消息服务,可显著降低运维负担。
五、ADR 的常见误区
误区一:把 ADR 写成详细设计
ADR 记录的是“为什么”,不是“怎么做”。详细实现应该放在设计文档、接口文档或代码注释里。
误区二:只记录最终方案
如果只写“我们选了 X”,那和没有记录区别不大。真正有价值的是被放弃的方案及其原因。
误区三:认为 ADR 一旦写下就不能改
ADR 不是圣旨。当业务、技术或团队条件变化时,可以新建一条 ADR 来取代旧决策,并把旧决策标记为Superseded或Deprecated。
误区四:追求完美格式而迟迟不动笔
ADR 最重要的是及时记录。哪怕最初只有背景、方案、理由三栏,也比事后回忆强得多。
六、如何在团队里落地 ADR
建议从三个动作开始:
-
建立 ADR 目录
放在代码仓库或文档仓库中,例如docs/adr/,按编号命名:001-mqtt-kafka-uplink.md。 -
规定触发条件
不是每个小决定都要写 ADR,但以下情况必须记录:- 引入新的中间件或框架;
- 改变系统边界或服务拆分;
- 调整数据模型或核心接口契约;
- 改变部署架构或运维方式;
- 推翻之前的架构决策。
-
在代码评审中引用 ADR
当有人质疑“为什么这么设计”时,直接给出 ADR 编号。这样既减少重复争论,也让新成员快速理解系统演进脉络。
七、总结
做架构设计不只是画出架构图就是完事了,还需要记录详细的架构决策。ADR就是这个好用的记录工具。
架构师的价值,不只体现在做出正确决策,更体现在让决策过程可被理解、可被质疑、可被迭代。
ADR 并不复杂,但它能把架构从“个人经验”变成“团队资产”。多年后,当你回头看一个系统,最珍贵的往往不是那张最终架构图,而是那些记录着“我们当时为什么这样选”的文字。
有了ADR,架构就是可推演的。你用过ADR吗?评论聊聊。
浙公网安备 33010602011771号