Appearance
如何出一个技术方案
定位:工程实践方法论。技术方案不是"把代码翻译成文档",而是在动手之前,用最低的成本把设计错误暴露出来。方案评审阶段改一行字,上线阶段可能就是一个故障。这篇整理出一份方案文档的骨架和每节要回答的问题。
骨架总览
一份能过评审、能指导开发、能兜住风险的方案文档,固定七节:
1. 背景与目标 —— 为什么做,做到什么程度算成
2. 方案对比 —— 为什么选这个,而不是别的
3. 详细设计 —— 怎么做:流程、数据、接口、异常
4. 容量估算 —— 系统扛不扛得住,要花多少钱
5. 灰度与回滚 —— 怎么安全地上,出事怎么退
6. 风险清单 —— 哪里可能出问题,各自怎么兜底
7. 排期与里程碑 —— 谁在什么时间交付什么前两节决定"该不该做、该这么做吗",中间三节决定"上线会不会翻车"。最后一节决定"什么时候能见到结果"。
一、背景与目标
要回答的三个问题:
- 业务背景:什么业务场景、什么具体困难、谁提的、多紧急。不要写"为了提升系统稳定性"这种空话,要写"大促期间订单查询 P99 超 3s,客服工单每天 +200"。
- 现状与问题:当前方案的数据流/架构描述 + 量化的问题指标。画现状架构图,标注问题发生在哪一环。
- 目标(可量化、可验收):
- 好的目标:"查询 P99 从 3 s 降到不超过 300 ms,大促峰值 10 万 QPS 下可用性 99.99%"。
- 坏的目标:"优化查询体验,提升系统性能"——无法验收,也就无法结项。
- 同时写非目标(Non-Goals):明确本期不解决什么,防止范围蔓延,也防止评审时被带偏。
二、方案对比
至少给出 2-3 个候选方案,包括"什么都不做"的基线。没有对比的方案,等于把选择权丢了。评审者不知道你为什么走这条路,也就无法判断这条路对不对。
对比维度
| 维度 | 说明 |
|---|---|
| 功能满足度 | 是否覆盖全部需求目标,有无语义损失 |
| 性能与容量 | 延迟、吞吐是否达标(引用容量估算数据) |
| 复杂度 | 开发量、依赖组件数、运维复杂度、团队熟悉度 |
| 可演进性 | 下期需求来了要不要推翻重来 |
| 风险 | 每个方案各自的失败模式 |
| 成本 | 机器/云资源费用、人力排期 |
写法要点
- 每个方案给出一图(流程/架构图)一段话(核心机制),不必等篇幅展开,重点讲差异点。
- 结论要明确:"选方案 B。放弃 A 的原因是 X(量化),放弃 C 的原因是 Y(量化)。"
- 被否掉的方案留着别删——半年后有人再提同样的想法时,这份对比就是决策记录。
三、详细设计
选定方案后展开,覆盖五个视角:
1)整体流程
- 核心链路的时序图/流程图:请求从哪进、经过什么、落到哪。
- 同步链路与异步链路分开画;标注每个边界的协议(RPC/MQ/HTTP)。
2)数据设计
- 表结构变更(新表 DDL / 老表加字段)、索引设计。
- 存量数据怎么办:要不要迁移、迁移方案、迁移期间新旧数据如何共存(详见兼容性篇)。
- 数据生命周期:增长速度、归档/清理策略。
3)接口设计
- 对内对外接口的签名、语义、错误码。
- 幂等性:重复请求的语义(尤其涉及写操作的接口)。
- 限流与鉴权:接口级别的保护。
4)异常与降级
- 每个依赖故障时的行为:失败重试几次、超时多少、最终是返回错误还是降级。
- 核心链路 vs 非核心链路划分:非核心可降级(开关一键关闭)。
5)监控与告警
- 上线看哪些指标(QPS/RT/错误率/资源水位),阈值多少告警给谁。
- 方案里没有监控设计等于盲飞——出问题时你没有观测手段。
四、容量估算
用数量级估算回答"扛不扛得住、要多少资源"。不需要精确,需要不差数量级。
估算套路
1)拿到业务量假设:日订单量 / 用户量 / 峰值系数(大促按日常 10 倍估)。
2)推导每类资源需求:
QPS = 日请求量 / 86400 × 峰值系数
存储 = 单条大小 × 日增量 × 保留天数 × 副本数 × 2(索引与膨胀)
内存 = 单请求峰值对象 × 并发数 + 缓存条目 × 单条大小
带宽 = 单请求平均报文 × QPS
连接 = QPS × 平均耗时(Little's Law:并发数 = QPS × RT)3)对照资源上限,算出冗余度:低于 50% 冗余就需要扩容或优化。
常见坑
- 只算应用服务器不算 DB:QPS 上去了,先死的是数据库连接数和磁盘。
- 只算均值不算峰值:压垮系统的是峰值,平均值只在报表里好看。
- 忘了 MQ/缓存等中间件的容量:消息堆积一天的磁盘、Redis 的内存水位。
- 忘了下游容量:自己扛住了,把下游打挂了,事故照样是自己的。
五、灰度与回滚
发布策略
- 发布顺序:依赖方先行(先建表、先发下游、最后发入口)。
- 灰度路径:白名单用户 → 1% → 5% → 20% → 50% → 100%,每档观察时长写明(如至少一个流量高峰周期)。
- 每一档观察什么指标、什么阈值触发暂停,提前写死,避免现场拍脑袋。
回滚方案
- 回滚是设计出来的,不是"把代码 revert 就行":
- 代码回滚:确认无不可逆变更(老代码能否读新格式的数据/消息)。
- 数据回滚:迁移类变更要有反向脚本或快照;DDL 尽量兼容式(先加后删,删放最后一步)。
- 配置回滚:开关默认值 = 安全值(老逻辑),出事关开关即回退。
- 回滚演练:第一次灰度前把回滚动作走一遍(至少预发环境),确保回滚路径真的通。
六、风险清单
逐条列出风险与对策,宁多勿漏。按影响 × 概率标级:
| 风险 | 影响 | 概率 | 对策 | 兜底 |
|---|---|---|---|---|
| 新缓存与 DB 不一致 | 数据错误 | 中 | 延迟双删 + 过期时间 | 对账任务校准 |
| MQ 消费积压 | 延迟上升 | 低 | 消费端扩容 + 告警 | 降级读库 |
| 存量数据迁移超时窗口 | 停机超时 | 中 | 分批迁移 + 断点续传 | 回滚到旧链路 |
三个必答题(答不上来就不要上线):
1)这个变更最坏情况影响什么、影响多大范围? 2)出问题后多快能发现(监控/告警覆盖了吗)? 3)发现后多快能恢复(回滚动作用时多少)?
七、排期与里程碑
- 按交付物拆分(DDL / 接口 / 联调 / 灰度 / 全量),不要按"开发 5 天"这种黑盒拆。
- 标出关键依赖路径与外部依赖方(需要别的团队配合的,提前锁定时间)。
- 留 buffer:联调 + 灰度观察时间通常被低估。
评审要点
评审会前发出文档(给评审者至少半天阅读时间),会上聚焦三类问题:
- 目标层:这个目标值得做吗?目标达成的验收方式成立吗?
- 方案层:对比是否充分?有没有更简单的做法?复杂度是不是过度设计?
- 风险层:容量估算靠谱吗?回滚真的可行吗?风险清单有没有漏项?
会上达成的修改意见当场记录到文档修订记录。方案文档随实现过程持续更新——它应该是活文档,结项时的版本就是系统的真实模样。
一句话总结
目标可量化、方案有对比、容量有账本、灰度有梯子、回滚有路、风险有清单。 六个"有"齐了,方案就立得住;缺任何一个,评审时被挑战的就会是那一节。
2026-10 依据主题重写(原文件为空壳)。