7AA7 Blog

技术选型的决策框架:如何避免拍脑袋

沈叙白 UID:72
2026-10-03 16:43
19 2 0

选型讨论里最常见的一种失效模式是:候选列了四五个,会议开了两小时,最后拍板的人说一句”我觉得 B 好一些”。这个结论本身不一定错,但它不可复用、不可追溯。半年后新人问”为什么是 B”,没人答得上来。

差别不在于选出哪个,而在于能不能把判断过程外化成一份别人能检查的东西。

约束先于候选

多数选型从”我们有哪些选择”开始,这个顺序是反的。候选空间在约束确定之前接近无限,先列候选等于把讨论锚定在几个恰好被想起来的名字上——通常是某人最近用过的,或者刚看过文章的。

先把约束写死,候选会自己收敛。约束至少覆盖四类:

约束维度 要回答的问题 典型硬约束示例
团队规模与构成 几个人维护?平均经验年限?有无专职运维 3 人以下不选需要独立运维集群的方案
交付时间 上线窗口多长?有无中期里程碑 6 周内上线不引入需要重写数据层的方案
运维能力 有无监控告警与值班?故障响应目标 无人值班时排除需手动干预才能恢复的组件
合规要求 数据能否出境?日志留存多久? 涉个人信息时排除无法私有化部署的 SaaS

约束分两种:硬约束是不满足就出局的过滤条件,软约束是进入评分的维度。把二者混在一起是评分表失效的头号原因——某方案在五个维度上总分最高,却在合规上直接不合格,最后照样被否,讨论白做。

加权评分表的生命线是打分依据

评分表的形式大同小异,真正决定它有没有用的是打分依据能不能被验证。

维度            权重   方案A(自建)  方案B(托管)  方案C(无新组件)
满足硬约束      过滤    不通过         通过          通过
学习成本        0.20    3             8             9
运维负担        0.25    2             9             7
吞吐上限        0.20    9             8             4
一致性保证      0.20    8             8             7
长期可持续性    0.15    7             6             8
加权总分        —       出局          7.95          7.20

权重应当来自约束,而不是来自”大家觉得哪个重要”。一个四五人的小团队把”生态活跃度”赋到 0.25 而”学习成本”只给 0.05,通常说明权重是照抄来的,没有过约束这一关。

打分依据要写成可复核的形式。不要写”性能:8 分”,要写”性能 8 分,依据:官方基准在 100 并发下 P99 约 40ms(附链接与测试条件),我们的目标是不劣于 100ms”。可验证的意思是:另一个人拿同一份依据能推出同样的分数。做不到这一点,评分表只是给个人偏好套了件外衣。

还有一步常被跳过:权重敏感性分析。把权重上下浮动 20% 再算一遍,若第一名换位,说明结论对权重设定过于敏感,此时应该回到约束重新讨论,而不是直接采纳当前第一名。

可逆性决定该花多少时间

决策按可逆程度分档,投入的时间应该跟档位匹配:

决策类型 例子 回退时要迁移的资产 建议投入
易逆 换日志库、换格式化工具 少量调用点 时间盒 1–2 天,到点就选
半逆 换序列化格式、换缓存中间件 已落盘的数据、客户端兼容 POC + 灰度
难逆 换主数据库、换编程语言 全部代码、数据、人员技能 完整流程 + POC + 回滚预案

判断依据不是”改代码难不难”,而是”回退时要迁移多少既有资产”——数据、代码、团队技能、运维流程四样加起来。

两条对等的错误:把不可逆决策当可逆的快做,代价是几年还债;把可逆决策当不可逆的慢做,代价是机会成本。后者更常见,也更隐蔽,因为它看起来很”严谨”。

“最熟悉”不等于”最合适”,但常常是对的

维护成本通常大于技术先进性带来的收益。团队熟悉 A、不熟悉 B,即使 B 在评分表上高出几分,选 A 往往仍然正确。理由可以写得更硬一点:

引入 B 的额外成本 ≈ 学习期效率折损 × 人数 × 月数
                  + 故障排查时长增加 × 预期故障次数
                  + 招人与交接成本

这不意味着永远选熟悉的。区分方法是看这个包袱要背多久:如果这次选型决定的是未来三年都要维护的东西,学习成本可以被摊销,值得为更好的特性付费;如果是一次性脚本、短生命周期服务,熟悉的胜出。

一条经验上的止损线:一个团队同时引入超过两个”大家都不熟”的核心组件时,故障率和延期概率会明显上升。要引入新东西,一次引入一个,并且尽量不放在关键路径上。

POC 只验证风险点

POC 最典型的失败是做成了 demo:happy path 跑通,宣布”技术可行”。可 happy path 从来不是风险所在。

正确做法是先从约束和评分表里找出这个方案的”致命未知”,然后只验证它,其余一概跳过。

例:引入一个新消息队列,风险点大概是——

  1. 高吞吐下会不会丢消息(而不是”能不能发出去”)
  2. 消费端积压到百万级后恢复要多久(而不是”能不能消费”)
  3. 节点故障时转移是否自动、数据是否还在(而不是”能不能启动”)

POC 的验收标准必须可判定,写成”在条件 X 下指标 Y 达到 Z 则通过”:

验收条件:5000 QPS 持续写入 30 分钟,期间 kill 一个 broker 节点
通过标准:消息零丢失,且消费端 P99 < 200ms
不通过的处理:直接记为不通过,不允许"再调调参数看看"

POC 同样要设时间盒与退出条件。是否继续投入取决于剩余风险有多大,而不是已经投了多少。

把决策写成 ADR

ADR(Architecture Decision Record)的最小结构如下,写完大约半小时:

# ADR-014: 订单创建链路异步化

- 状态:已接受(2026-10-21)
- 参与人:后端 4 人 + 一次架构评审

## 背景
订单创建同步调用 5 个下游,P99 约 1.2s,其中 3 个下游允许异步。
约束:4 人团队无专职运维;上线窗口 8 周;消息不允许丢失。

## 候选
A. 自建消息队列 —— 违反"无专职运维"硬约束,出局
B. 托管队列服务 —— 合规通过,运维负担低
C. 数据库表轮询(outbox)—— 无新组件,吞吐上限受限

## 决策
一期选 C。当前量级远低于 C 的上限,且零新增运维负担。
触发重评的条件:日订单量超过 X,或积压行数持续高于 Y。
迁移路径:C 的生产端表结构可直接对接 B,迁移仅限消费端改造。

## 后果
正面:链路 P99 下降,无新组件引入。
负面:轮询对主库有额外压力,需新增积压行数监控。
跟踪项:每周检查一次积压峰值。

ADR 的价值出现在半年后:当有人问”当初为什么不直接上托管队列”,答案连同当时的约束一起被保留下来,讨论就不必从零重来。末尾那句”触发重评的条件”尤其重要,它给决策设了有效期,避免它变成没人再敢质疑的默认。

一份可执行的选型清单

把上面的步骤压成一张检查表,评审时逐条打勾:

[ ] 硬约束已列出,且每个候选都做了通过/出局判定
[ ] 权重从约束推导,不是照抄模板
[ ] 每个分数都附了可验证依据(链接/实测/文档章节)
[ ] 做过权重敏感性分析,结论稳定
[ ] 已判定该决策的可逆档位,投入与之匹配
[ ] POC 验证的是风险点,有可判定的通过标准
[ ] ADR 已写,含背景、候选、决策、后果、重评条件
[ ] 明确了"这次不做什么"

选型的产出不是那个技术名字,是这一叠能被质疑的记录。名字会过时,记录里的推理方法不会。

557Views
19Likes
2Comments
2Participants
9 minread time

Comments (2)

  • 孟知微 · 2026-10-03 18:46

    看标题以为又是水文,读完默默点了关注。

    Reply
  • 许清欢 · 2026-10-04 03:51

    看完第一反应是:我们架构就是这么烂的。

    Reply