Aphasia

Cogito ergo sum.

引言:头顶的星空与心中的尺度

康德在《实践理性批判》的结尾写下了一段广为流传的话。不同译本的措辞略有差异,按其英文版本意译如下:

我们越是经常、越是持久地思考两件事,心中就越会生出历久弥新的惊叹与敬畏:头顶的星空,以及心中的道德律。

——伊曼努尔·康德,《实践理性批判》

“头顶的星空”把人放回广阔而有秩序的世界:我们能够通过观察和理性认识它,却也必须承认自身经验与认知的边界。“心中的道德律”则把目光转向人的内部:人在行动时不仅面对外部事实,也需要面对由理性、责任和原则构成的自我约束。

康德的哲学并不是为复杂问题提供几句可以直接套用的格言。相反,“批判”首先意味着审查理性的能力和边界:我们凭什么得到一个结论,这个结论在哪些条件下成立,又在哪些地方超出了可以正当使用的范围。对工程师而言,这种态度比任何一条具体“定律”都更加重要。

工程世界当然没有永恒不变的架构,也不能把软件经验与康德所说的道德律等量齐观。但我们同样面对两重尺度:外部是庞大、复杂且不断演化的系统,内部是对正确性、可靠性、诚实证据和工程责任的坚持。我们既要仰望系统所呈现的秩序,也要警惕自己的知识边界和判断偏差。

因此,本文收集这些工程定律,并不是为了寻找计算世界里不可动摇的教条,而是希望保留一组经过时间筛选的思考坐标:面对复杂性时有所敬畏,做出判断时有所依据,承担工程后果时有所约束。

1. 为什么还需要一份“工程定律”手册

工程工作里有一类问题很难只靠局部代码回答:为什么组织调整之后,系统边界也跟着变化?为什么增加机器后,查询速度没有线性提升?为什么一个兼容性改动会影响完全没有记录在文档里的用户?为什么项目的主流程很快完成,最后的工程化却迟迟不能收尾?

这些问题反复出现,于是人们把长期观察浓缩成了定律、原则、效应和箴言。它们不是用来替代分析的“标准答案”,而是帮助我们更早提出正确问题的思维索引。

这份手册主要面向数据库、查询引擎和分布式系统。它希望完成三件事:

  1. 把散落的工程经验组织成一套可以检索的框架;
  2. 把抽象表述映射到优化器、执行引擎、存储、协议和项目管理;
  3. 说明每条规律的边界,避免用一句名言终止讨论。

1.1 先区分“定律”的证据强度

这里收录的内容并不处于同一层次。

类型代表条目应该怎样使用
数学模型Amdahl、Gustafson写清变量和前提,用数据代入验证
不可能性结论CAP明确系统模型、故障条件和语义定义
经验规律Conway、Brooks、Lehman作为风险提示,再寻找当前项目的证据
设计原则KISS、DRY、YAGNI、SOLID用于比较方案,不能机械套用
认知偏差Confirmation Bias、Sunk Cost用来约束自己的决策过程,而不是给别人贴标签
讽刺或文化箴言Zawinski、Dilbert、Sturgeon用来提醒组织病灶,不能冒充科学结论

因此,本文最重要的使用原则是:

定律是发现问题的透镜,不是证明结论的证据。真正的工程结论仍然要落在 workload、指标、故障模型和代码路径上。

2. 架构:边界、抽象与复杂性

2.1 Conway’s Law:架构也是沟通结构的投影

Mel Conway 的原始表述可以概括为:设计系统的组织,最终会产出与组织沟通结构相似的系统。

数据库团队如果分别由 Optimizer、Execution、Storage 和 Cloud Infra 小组负责,系统通常也会形成相似的模块边界。这个映射本身并没有问题,危险在于组织接口不清晰时,模糊也会被写进系统:

  • Ownership 分裂,最终表现为跨模块状态重复维护;
  • 团队之间只能通过工单协作,最终表现为僵硬而冗长的接口;
  • 各团队只优化自己的指标,最终表现为局部最优、全局退化;
  • 组织变化很快,架构却保留着已经不存在的边界。

Conway’s Law 的实践价值不是“用组织解释一切”,而是要求架构评审同时检查技术依赖和协作依赖。想得到面向端到端链路的系统,通常也需要能够对端到端结果负责的团队。

检查问题:一个跨模块需求需要多少团队同步?接口的复杂性来自业务语义,还是来自 Ownership 的切割?

2.2 Leaky Abstractions:抽象不会消灭底层差异

Joel Spolsky 将这种现象称为抽象泄漏定律:足够复杂的抽象都会在某些时刻泄漏底层细节。

“统一存储接口”可以把 HDD、NVMe、本地缓存和对象存储都抽象成 read/write/scan,但延迟分布、一致性、Flush 语义、请求粒度和失败模式仍然不同。平稳运行时,上层只看到统一接口;性能抖动和故障发生时,底层差异会穿透抽象。

在数据库中,常见泄漏包括:

  • 统一 Join 接口泄漏 Hash Table 布局、Build/Probe 非对称性和 Spill 能力;
  • 统一 Cache 接口泄漏 Page Cache、Block Cache 和 Object Cache 的淘汰行为;
  • 统一 SQL 方言泄漏类型系统、NULL 语义和函数实现差异;
  • 存算分离接口泄漏网络 RTT、带宽竞争和远端限流。

好的抽象不是假装底层完全相同,而是同时提供稳定的公共语义、必要的能力描述和可追踪的诊断通道。

检查问题:故障时能否看到真正的后端、请求和重试?调用方是否能够表达 Locality、Consistency 或 Latency Budget?

2.3 Hyrum’s Law:所有可观察行为都可能成为契约

Hyrum’s Law指出:当 API 用户足够多时,契约中写了什么已经不重要;系统的所有可观察行为最终都会被某些用户依赖。

数据库用户依赖的往往不止 SQL 标准和公开 API,还包括:

  • EXPLAIN 和 Profile 的字段、顺序与文本格式;
  • 错误码、错误消息甚至大小写;
  • NULL 排序、隐式类型转换和结果列顺序;
  • Optimizer Rule 的副作用和 Hint 的边缘行为;
  • 配置项默认值、资源估算以及查询计划的稳定性。

这解释了为什么一次“内部重构”也可能造成兼容性事故。对于可观察面,应该先建立清单,再决定稳定等级:哪些是正式契约,哪些提供迁移期,哪些明确不保证稳定。无法无限兼容时,要提供版本化、弃用告警和替代路径,而不是假设“文档没写,用户就不会用”。

检查问题:这次改动改变了哪些可观察行为?仓库外是否有脚本、平台或 SDK 在解析它?

2.4 Gall’s Law 与 Second-System Effect:复杂系统只能从可工作的内核长出来

Gall’s Law 强调,能工作的复杂系统通常由能工作的简单系统演化而来;从零设计的复杂系统往往难以工作。Second-System Effect 则提醒我们:第一个系统成功之后,第二版最容易把积压的想法一次性装进去,最终过度设计。

在查询引擎中,“实时与离线统一、跨源联邦、自动物化视图、增量刷新、智能推荐、跨云容灾”都可能是合理目标,但不能同时作为最小闭环。更稳健的演进顺序是:

1正确执行一个核心场景
23    ├─► 建立可观测性和失败语义
45    ├─► 覆盖更多数据规模与边界条件
67    └─► 在真实反馈上增加自动化与通用性

设计第二代 Planner、Storage Format 或 Scheduler 时,先列出第一代真正被验证的核心价值,再列出必须解决的结构性问题。所有“顺便重做”的内容都应该重新证明收益。

2.5 Tesler’s Law:复杂性只能被分配

系统中存在无法消除的必要复杂性。产品可以把分区、Compaction、Rebalance 和故障恢复隐藏起来,让用户获得简单体验,但这些复杂性会转移到内核、控制面和运维系统。

这不是反对易用性,而是要求设计者回答三个问题:

  1. 哪些复杂性属于问题本身,哪些是当前实现制造的?
  2. 必要复杂性应该由用户、Planner、Runtime 还是运维系统承担?
  3. 承担复杂性的那一层是否拥有足够的信息、资源和可观测性?

复杂性转移只有在接收方更有能力处理它时才有价值。把用户侧配置变成系统内不可解释的“智能决策”,只是把显式复杂性换成了隐式风险。

2.6 架构类扩展原则

原则核心提醒数据库场景边界
Premature Optimization没有测量就不要提前优化为假想热点引入复杂 SIMD、Cache 或 Codegen 路径不是反对前置容量设计和已知热点优化
Law of Unintended Consequences改动会产生连锁副作用调整 Cost Model 后改变 Join 顺序、内存峰值和调度并发用灰度、回滚和观测控制风险,不是停止变化
Zawinski’s Law程序倾向不断扩大职责工具变平台,平台再承担 Catalog、调度和治理属于讽刺性提醒,不是经验定理
The Map Is Not the Territory模型不是现实本身Cost、统计信息和架构图都只是运行时系统的近似模型仍然必要,但要用实际 Profile 校准

3. 分布式系统与规模:先写清前提,再谈扩展

3.1 CAP:不是“任意选择两个字母”

CAP 最常见的误读是“一致性、可用性、分区容错三选二”。Gilbert 和 Lynch 对 CAP 的形式化讨论关注的是:在允许网络分区的异步模型中,系统无法同时保证原子一致性和每个请求都能得到响应。具体定义和模型可参见论文 Perspectives on the CAP Theorem

工程上真正要写清的是分区发生时的行为:

问题偏一致性的选择偏可用性的选择
元数据多数派不可达拒绝写入或等待仲裁接受本地写入,之后解决冲突
跨 Region 读等待确认或只读 Leader允许 Stale Read
Lease 状态不确定停止服务以避免双主继续服务并承担语义冲突
分布式事务协调者失联保持 Pending 并恢复决议超时后做补偿或弱化语义

CAP 也不是系统的完整分类。现实设计还要考虑延迟、一致性级别、故障持续时间、数据丢失窗口和恢复复杂度。比“我们是 CP 还是 AP”更有价值的问题是:哪种请求在什么故障下返回什么结果,恢复后如何收敛?

3.2 分布式计算的八个谬误:把网络当作故障域

分布式设计经常无意识地假设网络可靠、延迟为零、带宽无限、网络安全、拓扑不变、只有一个管理员、传输零成本且网络同质。这些假设在 Remote Cache、Shared Storage、Remote Spill 和跨 Region 事务中尤其危险。

设计不能只补一个 Retry:

  • Timeout 必须绑定端到端 Deadline,避免逐层重试放大延迟;
  • Retry 需要退避、抖动、幂等和预算;
  • 慢节点要被当作故障,而不只是性能波动;
  • 队列和连接池必须有上界,防止局部故障扩散;
  • Profile 要区分排队、网络、远端执行和重试时间;
  • 降级路径必须定义数据语义,不能只保证“接口还返回 200”。

3.3 Amdahl’s Law:优化上限由串行部分决定

若程序中可并行比例为 P,使用 N 个并行单元时的理论加速比为:

1               1
2S(N) = -------------------
3       (1 - P) + P / N

P = 0.95 时,即使 N 无限大,理论加速比也不会超过 20。这 5% 可能是 Coordinator 串行规划、Metadata Fetch、Final Merge、Commit、全局 Barrier,或者无法切分的热点分区。

这条规律改变了性能分析的顺序:不要先问“还能增加多少并行度”,而要先从 Critical Path 上找不可并行、不能重叠或必须全局同步的部分。单个算子 CPU 占比高,不等于它就是端到端加速的第一目标。

3.4 Gustafson’s Law:扩展也可以意味着解决更大的问题

Amdahl 假设问题规模固定,Gustafson 则讨论资源增加时问题规模也随之增长的场景。若串行时间占比为 αN 个处理单元的缩放加速可写为:

1S(N) = N - α × (N - 1)

两者并不冲突:

  • Amdahl 回答“同一份数据最多能跑快多少”;
  • Gustafson 回答“在近似相同时间里能否处理更大的数据”。

对 OLAP 系统,Scale-up 测试应同时报告固定数据量的加速效率,以及 1 TB、10 TB、100 TB 等同比扩容下的单位资源效率。只展示其中一种,很容易掩盖串行瓶颈或规模红利。

3.5 Metcalfe’s Law:生态连接有价值,但不是严格平方关系

Metcalfe’s Law 常用参与者两两连接数量解释网络价值。对数据平台而言,Connector、Table Format、Catalog、BI、ETL 与 AI 工具的互操作性确实会放大平台价值。

不是普适的产品估值公式:连接质量、参与者活跃度、治理成本和跨系统语义一致性同样重要。十个稳定、可维护的连接通常比一百个“能连上但不能正确演进”的适配器更有价值。

4. 演化与质量:系统不是交付后就静止的作品

4.1 Lehman’s Laws:活着的软件必须演化,也会积累复杂性

Lehman 对现实环境中持续使用的软件进行了长期研究。核心观察是:系统若不随环境和需求变化,就会逐渐失去价值;而持续变化会增加复杂性,除非团队主动投入维护和简化。相关背景可参见论文 Software evolution—Background, theory, practice

数据库长期演化后会自然出现 Legacy Config、兼容分支、旧 Planner 路径、格式迁移和多代协议并存。问题不在于这些东西“看起来不够优雅”,而在于新增功能、兼容承诺和清理能力是否失衡。

因此,重构、弃用、可观测性和迁移工具不是 Feature 之外的额外工作,而是保持演化能力所需的固定预算。

4.2 Technical Debt:债务的关键是未来利息

技术债最有用的地方是“债务”这个隐喻:当前采用权宜方案换取速度,同时接受未来返工和持续利息。它不等于所有旧代码、丑代码或自己不熟悉的代码。

判断一项问题是否值得优先偿还,可以估算:

1技术债优先级 ≈ 未来变更频率 × 单次额外成本 × 影响范围 × 风险系数

例如 Rule 顺序写死,如果两年都不会改变,它可能只是难看的实现;如果每个新规则都要修改多处、反复引入回归,它就在持续产生利息。债务清单应该记录本金、利息、触发条件、Owner 和偿还方案,而不是堆积没有决策信息的 TODO。

4.3 Postel’s Law:宽容输入并非总是安全

Postel’s Law 常被概括为“发送时保守,接收时宽容”。它曾帮助协议在异构实现间互操作,但过度宽容也可能带来解析歧义、安全漏洞和事实标准分裂:A 接受的非法输入,经过 B 转发后可能产生不同语义。

在现代数据库协议和配置解析中,更稳健的做法往往是:

  • 输出遵循明确、版本化的规范;
  • 对可安全归一化的差异保持兼容;
  • 对歧义、越界和未知关键字段严格失败;
  • 弃用行为有告警、指标和截止版本。

兼容性不是“什么都接受”,而是在可预测语义内接受演进。

4.4 从“会出错”推导质量体系

Murphy’s Law 提醒我们,会出错的路径最终可能出现;Testing Pyramid 提醒我们建立不同粒度、反馈速度和成本的测试组合;Pesticide Paradox 则提醒固定测试集会逐渐失去发现新缺陷的能力。

对数据库内核,一套更实用的测试组合是:

测试层主要职责典型对象
单元与属性测试快速验证局部不变量Expression、编码、Hash/Compare、Rule
组件测试验证模块协作和故障分支Spill、Compaction、WAL、统计信息
SQL 回归与差分测试验证语义和兼容性查询结果、类型系统、优化前后等价性
端到端与升级测试验证真实部署链路扩缩容、升级回滚、跨版本协议
压力与故障注入发现时序和资源边界OOM、磁盘满、丢包、慢节点、重启

Test Pyramid 是关于成本和反馈速度的启发式模型,不是要求所有系统都画出相同比例。数据库大量正确性问题横跨 Optimizer、Runtime 和 Storage,组件测试、SQL 差分测试可能比传统 UI 系统占比更高。

4.5 质量类扩展原则

原则可执行解释使用边界
Broken Windows过期注释、失效测试和无 Owner 模块会降低后续维护标准只把它当工程卫生隐喻;其社会学外推存在争议
Linus’s Law更多有能力且有动力的评审者能提高缺陷暴露概率“看的人多”不等于有效评审,仍需测试和责任闭环
Kernighan’s Law写到能力上限的巧妙代码,调试时往往超出能力上限性能敏感代码可以复杂,但要用测试、注释和基准约束
Sturgeon’s Law热门内容和工具也需要筛选属于讽刺性概括,不能代替具体评估

5. 设计原则:目标是降低变化成本,不是追求形式正确

DRY、KISS、SOLID、Law of Demeter、Principle of Least Astonishment 和 YAGNI 经常一起出现,但它们可能互相拉扯。抽取统一框架符合 DRY,却可能违反 KISS 和 YAGNI;隐藏实现细节符合 Demeter,却可能增加性能关键路径的抽象成本。

原则更准确的关注点常见误用
DRY同一份知识应有唯一权威来源仅因为两段代码长得相似就强行抽象
KISS选择满足约束的最简单方案用“简单”掩盖错误或遗漏的边界条件
SOLID管理职责、依赖和可替换性在数据导向或性能敏感代码中堆叠对象层次
Law of Demeter限制对遥远内部结构的了解为每个字段机械增加转发接口
Least Astonishment行为符合目标用户已经形成的模型假设所有用户拥有相同直觉
YAGNI不为尚未发生的需求支付实现成本忽略已知容量边界、迁移能力和不可逆格式决策

原则冲突时,应该回到变化方向:未来最可能变化的是什么?哪些约束不可逆?性能和可维护性的证据是什么?设计原则提供比较维度,而不是按命中条目数量给方案打分。

6. 团队与项目:软件的瓶颈经常不在代码里

6.1 Brooks’s Law:延期项目不能靠机械加人恢复

Optimizer、Storage Format、分布式事务和 Scheduler 都高度依赖上下文。新人加入后需要学习,核心成员需要带教,沟通路径也随人数增加。因此,给已经延期的项目加人,短期内可能进一步降低有效产出。

这不意味着加人永远无效。当工作可以独立拆分、接口稳定、交付周期足够长时,增加人员仍然有价值。真正的判断顺序应该是:

  1. 延期来自工作量、关键路径、决策等待,还是质量返工?
  2. 是否能缩小 Scope 或提前交付闭环?
  3. 新工作能否与关键路径解耦?
  4. 谁来承担学习和沟通成本?

6.2 Bus Factor:关键知识不能只存在于一个人的上下文里

如果 CBO、MV Rewrite、存储格式或恢复协议只有一个人敢改,团队拥有的不是“不可替代的专家”,而是高风险的知识单点。

降低风险不能只靠补文档。设计文档、代码评审、Backup Owner、轮值 On-call、故障演练和跨人主导改动需要组合使用。最有效的验证是:让非原作者完成一次真实变更、上线和故障定位。

6.3 规模扩大后的协调损耗

Ringelmann Effect 提醒团队规模扩大后,人均有效贡献可能下降;Dunbar’s Number 提醒稳定的人际关系存在认知上限。这些数字和效应不应被当成精确组织公式,但它们共同指出:组织一旦越过熟人协作规模,就必须依赖清晰接口、书面决策和小队自治。

Price’s Law 常被用于描述贡献分布高度不均,但它不是可靠的通用定量定律,更不能成为长期依赖“英雄”的理由。关键贡献者需要得到保护,同时也必须把系统能力沉淀到团队。

6.4 计划为什么总在最后失真

规律它提醒的风险应对方式
Parkinson’s Law工作会扩张到填满可用时间设 Must-have、Nice-to-have 和 Cut Line
Ninety-Ninety Rule主流程完成不等于可上线单独估算兼容、可观测、回滚和故障路径
Hofstadter’s Law复杂工作存在系统性估时偏差用历史数据、区间估计和阶段性校准
Gilb’s Law重要目标需要某种可观测尺度即使不能精确测量,也先定义代理指标和误差
Goodhart’s Law指标一旦成为单一目标就会被优化失真使用指标组合、护栏指标和人工复核

例如只追求 TPC-DS 总分,可能牺牲真实 Workload、P99、资源公平和可维护性;只追求 Cache Hit Ratio,可能通过缓存低价值对象让指标更好,却增加内存占用。指标设计必须同时回答:它代表什么、遗漏什么、如何被投机优化。

6.5 组织类讽刺原则的正确位置

Putt’s Law、Peter Principle 和 Dilbert Principle 都指向技术能力、管理权力与岗位匹配之间的张力。它们更适合作为组织反思的入口,而不是给个人下结论。

值得检查的是:技术决策是否有真正理解系统的人参与?晋升是否评估新角色所需能力?管理岗位是否成了唯一的成长路径?把问题改写成制度问题,通常比引用讽刺原则评价某个人更有建设性。

7. 决策与排障:先管理认知,再管理复杂系统

7.1 Confirmation Bias:主动寻找能推翻自己的证据

排障最危险的时刻,是在数据不足时先形成了一个生动解释:“一定是网络”“一定是磁盘”“一定是刚合入的 Optimizer 改动”。之后,人会更关注支持该判断的指标,忽略相反证据。

更可靠的排障记录应该同时包含:

项目内容
现象精确到时间、范围、请求类型和异常指标
候选假设至少列出两个可以竞争的解释
支持证据当前数据为何提高该假设的可能性
反证条件看到什么就应该放弃该假设
下一步实验成本最低、区分度最高的验证动作

Confirmation Bias 应首先用来约束自己,而不是在评审中宣称对方“有偏见”。

7.2 Occam 与 Hanlon:是搜索顺序,不是事实裁判

Occam’s Razor 建议在多个解释都能覆盖现象时,优先验证假设更少的解释。系统突然变慢时,先检查 Workload、配置、缓存和后台任务,通常比直接猜测 CPU 微码或编译器错误更高效。

Hanlon’s Razor 则提醒跨团队问题先检查疏漏、信息不对称和边界不清,不要直接归因恶意。两者都只是调查顺序:简单原因和无意错误更常见,但不能因此排除复杂故障或安全攻击。

7.3 Sunk Cost 与 Inversion:让未来收益决定未来投入

一个方向投入半年,并不会自动提高它未来成功的概率。判断是否继续时,可以问:如果今天第一次看到现有证据,我们还会选择这条路吗? 已经花掉的成本只应作为经验输入,而不应成为继续投入的理由。

Inversion 从反面补充这一判断:

  • 什么 Workload 一定会把这个方案打崩?
  • 哪三条路径最容易造成不可恢复的数据错误?
  • 哪个依赖一旦行为变化,我们就无法回滚?
  • 如果项目半年后失败,最可能的原因是什么?

先构造失败,再检查方案是否具备隔离、观测和恢复能力,通常比笼统询问“大家觉得方案怎么样”更有效。

7.4 First Principles:在惯性最强的地方重新推导

第一性原理要求把问题拆到基本约束,再重新推导方案。它适合挑战“我们一直这样做”的关键设计,例如:为什么必须依赖本地盘?为什么这个状态必须全局一致?为什么 Hash Table 必须完整驻留内存?

但从头推导本身成本很高。成熟协议、文件格式和算法中包含大量已经被事故验证的知识。第一性原理不是忽略历史,而是把历史方案还原成约束,区分哪些约束仍然存在,哪些只是路径依赖。

7.5 决策类扩展模型

模型有价值的提醒使用边界
Pareto Principle少数查询、路径或用户可能主导大部分成本80/20 不是固定比例,要用数据找实际分布
Dunning-Kruger Effect知识不足时也可能缺少校准能力用于自省和引入校验,不能用于嘲笑异议者
Hype Cycle / Amara’s Law人们可能短期高估、长期低估新技术不能据此预测任何具体技术一定成功
Lindy Effect经历长期使用的非易腐技术包含存活信号老并不等于适合当前约束,新技术也可能解决新问题
Cunningham’s Law公开的错误说法常能迅速引来纠正属于网络文化观察,不应通过故意误导获取答案

7.6 把一句定律改写成可证伪的 ADR

如果一个“定律”不能改变验证动作,它在评审里通常只是修辞。更有效的做法,是把它写成一条轻量 Architecture Decision Record:

 1Observation:
 2  当前观测到什么,而不是我们相信什么?
 3
 4Law / Model:
 5  哪条规律提示了哪一种风险?它属于数学结论、经验规律还是比喻?
 6
 7Hypothesis:
 8  在当前系统约束下,具体会出现什么可观测后果?
 9
10Falsifier:
11  哪个数据、实验或调用方检索结果会推翻假设?
12
13Decision:
14  选择什么方案,接受什么代价?
15
16Revisit Trigger:
17  Workload、团队、规模或故障模型发生什么变化时重新评估?

例如引用 Conway’s Law,不应直接得出“按团队拆服务”,而应形成可验证假设:跨团队接口的变更 Lead Time 与故障恢复时间是否显著更高?如果数据并不支持,就不应该为了组织图机械拆分系统。引用 Amdahl’s Law,也不应只计算一个理论上限,还要通过 Profile 找到真正的串行区间,并确认优化后瓶颈是否迁移。

这种写法保留了工程定律的启发价值,又强迫结论回到证据、约束和复查条件。

8. 面向数据库工程的十条常驻模型

如果只保留十条,我会选择下面这组。它们覆盖系统设计从需求、实现到上线和演化的主要风险。

模型常驻问题
Conway’s Law这个架构边界是否只是组织边界的偶然投影?
Leaky Abstractions底层差异会从哪里泄漏,如何诊断?
Hyrum’s Law哪些非正式行为已经被外部依赖?
Gall’s Law最小可工作闭环是什么?
Amdahl’s LawCritical Path 上真正串行的部分在哪里?
CAP分区发生时,每类请求的确定语义是什么?
Distributed Computing Fallacies网络慢、断、抖和重复时会发生什么?
Lehman’s Laws演化复杂度和清理预算是否平衡?
Goodhart’s Law指标变成目标后会怎样被优化失真?
Confirmation Bias什么证据能够推翻当前判断?

9. 把定律变成评审与排障清单

9.1 架构评审

  • 系统边界和团队 Ownership 是否一致且可演进?
  • 抽象隐藏了什么,哪些差异必须显式暴露?
  • 用户可观察面是否有版本化和兼容策略?
  • 分区、慢节点和局部失败时,各类请求的语义是什么?
  • 必要复杂性被转移给哪一层,它是否有能力承担?
  • 能否先交付一个可运行、可观测、可回滚的最小闭环?

9.2 性能优化

  • 结论来自 Profile 和基准,还是来自对热点的想象?
  • Critical Path、CPU 总量和资源峰值是否被混为一谈?
  • 串行部分、全局 Barrier 和热点分区在哪里?
  • 固定规模加速与同比扩容效率分别如何?
  • 哪些 Query 或路径主导实际成本?
  • 优化目标是否诱导 Benchmark 特化或牺牲 P99、正确性和公平性?

9.3 项目计划

  • 主流程之外,是否单独估算测试、兼容、灰度、回滚和观测?
  • 延期的真正瓶颈能否通过加人解决?
  • 是否存在只有一个人掌握的关键上下文?
  • Scope 是否有明确 Cut Line?
  • 如果今天从零决策,是否还会继续当前方向?

9.4 故障排查

  • 现象的时间、范围、版本和 Workload 是否已经固定?
  • 当前有哪些竞争性假设?
  • 什么证据能推翻最偏爱的假设?
  • 是否先验证了配置、负载、缓存和依赖变化等简单原因?
  • Retry、Timeout 或降级是否正在放大原始故障?
  • 恢复服务之后,是否验证数据语义和积压任务已经收敛?

10. 结语:用定律打开讨论,而不是结束讨论

工程定律最大的价值,是把个人经验压缩成可以共享的提问方式。它们能提醒我们关注抽象泄漏、串行瓶颈、网络分区、兼容性、组织接口和认知偏差,却不能直接证明某个方案正确。

一次有价值的引用应该完成三步:

  1. 指出风险:这次变更可能触发 Hyrum’s Law;
  2. 转成问题:哪些可观察行为可能已被依赖?
  3. 要求证据和行动:检索调用方、运行兼容测试,并设计迁移期。

只说“这是 Conway’s Law”或“根据 CAP 做不到”,很容易变成名词压制。把定律翻译成可证伪的问题、可观测的指标和可执行的动作,它们才会从鸡汤卡片变成真正的工程工具。

参考资料