在约束条件下做架构决策,支撑系统持续演进的思维模型。
系统设计关注的是:
系统设计 = 约束下的架构决策过程
功能回答的是:
系统设计回答的是:
因此,系统设计的核心关注点是:
这些被统称为:系统的质量属性。
业务目标
↓
约束条件
↓
架构决策
↓
实现机制
↓
系统能力
↓
验证/演进
系统首先服务于业务目标,而不是技术理想。
常见目标包括:
没有业务目标的系统设计,只是在堆复杂度。
约束决定了设计空间的边界。
常见约束包括:
约束不是负担,而是设计的前提条件。
系统设计的核心不是"选什么技术",而是做出结构性决策,结构性决策定义了"系统是什么形态":
每一个决策,本质上都是在约束条件下做取舍——用某些能力的损失换取其他能力的获得。
设计决策最终沉淀为系统的能力边界:
设计决策需要落地为具体实现方案。
关键实现要素:
实现层是"决策"转化为"能力"的桥梁,也是最容易引入复杂度的地方。
系统能力需要通过度量验证,并随业务演进。
验证机制:
演进机制:
缺乏验证的架构决策是无法迭代优化的赌博。
架构决策的结构化思考框架,而非具体技术方案
系统设计方法论回答一个根本问题:如何在动手之前,先想清楚?
它的价值在于:避免凭感觉决策、避免遗漏关键要素、避免在错误的方向上走太远。
合适原则 — 优秀架构是约束条件下的最优解,而非技术选型的最优解。大公司方案在小团队往往是灾难。
何时不适用:当合规要求、技术债临界点或组织惯性强制指定了某种方案时,"合适"需要重新定义。此刻的"不合适"可能源于历史包袱而非理性选择,此时的优先级是识别约束的本质可塑性,而非盲目顺从。
简单原则 — 复杂不会让系统更可靠,只会让它更难维护。简单方案和复杂方案都能满足时,选简单的。
何时不适用:高性能计算、硬实时系统、金融级一致性的场景中,适度复杂性是满足指标的代价。此刻的"简单"可能是性能或正确性的敌人,简单原则让位于能力交付。
演化原则 — 没有一步到位的架构。架构的生命力在于持续迭代,而非一步登天。
何时不适用:当系统核心抽象已经固化、上下游依赖已锁定、改造风险远大于收益时,激进重构是陷阱而非机会。此刻的"演化"应改为局部优化与渐进改良,而非推倒重来。
识别复杂度 → 设计备选方案 → 评估选择 → 详细设计
核心价值:避免在错误的复杂度上投入,以及在错误的方向上走太远。
| 步骤 | 目的 |
|---|---|
| 识别复杂度 | 做对的事,而非做多的事 |
| 设计备选方案 | 不把鸡蛋放一个篮子 |
| 评估选择 | 用约束而非感觉决策 |
| 详细设计 | 确保方案能落地 |
做什么:找出真正的能力缺口,而非功能需求。
系统设计的起点不是"要做什么功能",而是"当前系统缺什么能力"。
| 类型 | 本质 |
|---|---|
| 高性能 | 单机瓶颈 vs 水平扩展能力 |
| 高可用 | 故障容忍度与恢复速度 |
| 可扩展 | 需求变化的响应成本 |
关键:不是每个系统都需要高大全。识别出当前阶段下的1-2个主要矛盾即可。
常见错误:用想象的需求替代实际需求,为"未来可能"提前买单。
做什么:设计3-5个有显著差异的方案。
方案之间必须有架构级差异(如主备 vs 集群 vs 分片),而非细节差异(如检测周期1分钟 vs 5分钟)。
关键约束:
做什么:建立评估矩阵,从多维度权衡。
核心维度:性能、可用性、硬件成本、项目投入、复杂度、可扩展性。
选择原则:最简单优先、最合适优先、最熟悉优先。
做什么:将选定的方案落实到关键技术细节。
确定:部署架构、配置参数、接口协议、数据模型。
| 阶段 | 自检问题 |
|---|---|
| 开始前 | 真正的复杂度是什么?还是在解决假问题? |
| 备选方案 | 有没有明显差异的多个方案? |
| 评估选择 | 决策依据是什么?还是凭感觉选? |
| 详细设计 | 细节是否足以落地? |
HLD 回答"系统由什么构成",LLD 回答"每个部分怎么实现"。
系统设计天然分为两个层次:
分层是为了让不同角色、不同阶段关注不同层次的问题,避免认知过载。
HLD 是系统的"航拍图"——展示整体结构、主要组件及其交互关系,但不触及实现细节。
| 要素 | 说明 |
|---|---|
| 系统架构 | 主要组件、组件间关系、部署结构 |
| 服务划分 | 模块边界、职责定义、服务间接口 |
| 数据流 | 模块间数据流动方向 |
| 技术栈 | 框架、数据库、中间件选型 |
| 约束权衡 | 性能、安全、成本的权衡决策 |
产出物:架构图、服务/模块职责定义、API 接口概览、数据存储策略、关键设计决策。
LLD 是 HLD 每个组件的"施工图纸"——细化到类、方法、算法、数据结构。
| 要素 | 说明 |
|---|---|
| 类/模块设计 | 类图、方法签名、模块接口 |
| 算法逻辑 | 关键算法的伪代码或流程 |
| 数据结构 | 具体的数据 schema、索引 |
| 错误处理 | 异常场景、边界条件 |
产出物:类图与时序图、详细接口定义(请求/响应格式)、数据库表结构、单元测试计划。
| 维度 | HLD | LLD |
|---|---|---|
| 视角 | 整体 | 局部 |
| 粒度 | 组件级 | 类/方法级 |
| 关注 | 结构与关系 | 逻辑与实现 |
| 指导 | 协调与评审 | 开发与测试 |
| 产出 | 架构图 | 类图/时序图 |
| 问题 | 本质 |
|---|---|
| HLD 太粗 | 缺乏关键设计决策,只画方块图 |
| HLD 太细 | 把 LLD 当 HLD 写,层次不清 |
| LLD 缺失 | 开发人员自由度过大,偏离设计意图 |
| 两者脱节 | HLD 描述的架构在 LLD 中未体现 |
系统设计不只是计算 QPS 和画架构图,更重要的是在多重约束下做取舍。
权衡之所以存在,两个根本原因:
资源有限 — 预算、人力、时间都是有限的,在有限资源下追求 A 能力,必然挤压 B 能力的空间。
能力互斥 — 有些能力本身就不能共存,选择强一致性就必然放弃可用性,选择高安全就必然增加复杂度。
任何提升都有代价,代价必须在设计阶段被显式接受,而非在故障后被动承受。
| 此处追求 | 代价是 | 典型场景 |
|---|---|---|
| 性能 | 简单性、运维成本 | 过度优化 |
| 强一致性 | 可用性、响应时间 | CP 系统 |
| 水平扩展 | 分布式复杂度 | 分片、多副本 |
| 安全性 | 开发效率、用户体验 | 强鉴权 |
| 交付速度 | 架构质量 | 技术债 |
知道什么不该做,与知道什么该做同样重要。
| 反模式 | 本质 | 危险信号 |
|---|---|---|
| 银弹思维 | 相信某方案能解决所有问题 | 用同一技术套所有场景 |
| 过度设计 | 为"未来可能"提前付出代价 | 在解决不存在的问题 |
| 最小化陷阱 | 用短期便利替代长期收益 | 技术债只增不减 |
| 权威依赖 | 因"大厂这样做"而忽视上下文 | 问"XX怎么做"而非"我的约束是什么" |
| 沉默的代价 | 代价存在但从未被显式讨论 | 没人能解释"为什么这样做" |
系统设计能力的本质:不是知道多少种方案,而是知道在什么约束下放弃什么。
| 阶段 | 核心关注 |
|---|---|
| 小规模 | 简单性、开发效率 |
| 中规模 | 扩展性、可用性 |
| 大规模 | 伸缩性、治理能力 |
系统设计不是一次性工作,而是伴随系统生命周期持续发生的决策过程。
优秀的系统设计,不在于一开始就"设计得多复杂",而在于:
系统是否能够在不断变化的约束下,持续演进而不失控。