Skip to content

第 2 讲:架构设计三原则与四步法

核心结论(10 条必记)

  1. 合适原则:合适优于业界领先 -- 架构要匹配业务规模、团队能力、资源约束
  2. 简单原则:简单优于复杂 -- 能用简单方案解决的,不要用复杂方案
  3. 演化原则:演化优于一步到位 -- 架构是演进的,不是一开始就设计完美的
  4. 四步法第一步:识别复杂度(最重要) -- 方向错了,后面都白搭
  5. 四步法第二步:设计 3-5 个备选方案 -- 有差异性,不是同一方案的变体
  6. 四步法第三步:多维度评估,选最合适的 -- 综合考虑团队能力和资源约束
  7. 四步法第四步:细化落地,输出设计文档 -- 架构设计文档是可追溯的重要产出
  8. 三原则的关系:合适定方向、简单定方案、演化定时机
  9. 不要为"设计模式"而设计,忘了目的是解决问题
  10. 如果用一张 A4 纸画不清楚系统架构,那可能太复杂了

一、为什么需要架构设计原则和方法?

场景 1:无从下手

产品经理: "我们要做一个秒杀系统。"

开发小李: "好的......然后呢?我该怎么开始设计架构?"

小李百度了几十篇文章,每篇都不一样,最后更迷茫了。

问题:缺乏系统化的设计方法

场景 2:决策困难

架构评审会上: 小王说性能最好选 A,小张说可用性最高选 B,小刘说最简单选 C。 会议开了两小时,没有结论。

问题:缺乏决策原则

场景 3:过度设计

某创业公司,产品还没上线,3 个开发,技术负责人决定用微服务 + 异地多活 + Kubernetes,"一步到位"。 三个月后,系统还没上线,钱快烧完了。

问题:违反了架构设计原则


二、架构设计三大原则

原则一:合适原则

合适优于业界领先。

架构设计首先要合适,不是追求最先进。合适意味着与业务规模、团队能力、资源约束相匹配。

架构是有成本的(开发、维护、学习、运维),越复杂的架构成本越高。如果业务规模撑不起这个成本,再先进的架构也是负担。

反面案例

案例 1:创业公司照搬阿里中台

某创业公司(20 人、日活 5000、业务还在探索期)决定搞中台。 花了半年搭中台,业务迭代严重滞后,最后公司倒闭了。

阿里中台是为了支撑几十个业务线、几万人协作,创业公司根本不需要。

案例 2:3 人团队搞 20 个微服务

每个人要维护 6-7 个服务,排查问题要跨多个服务,部署、测试、运维都很痛苦,效率反而下降。

微服务有"三个火枪手原则":一个服务最好 3 个人维护。3 个人最多维护 1-3 个服务。

正面案例:Instagram 的单体架构

2012 年被 Facebook 收购时,13 名员工服务 3000 万用户,用的是最简单的 Django 单体架构。后来用户增长到几亿,才开始做服务拆分。

早期选择了合适的架构,把精力放在产品上,等业务真正需要时再演进。

如何判断"合适"?

维度问题
业务规模当前用户量、数据量、并发量?未来 1 年预期?
团队规模有多少开发?多少运维?技术水平?
资源约束有多少预算?多少时间?
业务阶段MVP 探索期?快速增长期?稳定期?

如果这个架构方案的维护成本超过了它带来的收益,那就是不合适的。


原则二:简单原则

简单优于复杂。

能用简单方案解决的,不要用复杂方案。复杂度是架构的敌人,简单的系统更容易理解、维护、演进。

软件系统有个规律:复杂度会随着时间指数级增长。 一开始就很复杂,一年后没人看得懂,两年后只能推倒重来。

反面案例

案例 1:过度抽象

某订单系统搞了订单工厂、订单策略、订单适配器、订单建造者、订单装饰器、订单代理...... 一个简单下单流程代码跳了十几层,新人三个月看不懂,改个小功能要改十几个类。

为了"设计模式"而设计,忘了目的是解决问题。

案例 2:过度技术栈

后端 Java + Go + Python + Node.js,数据库 MySQL + PostgreSQL + MongoDB + Redis + ES,消息队列 Kafka + RabbitMQ + RocketMQ...... 没人能全部掌握,招人困难,运维噩梦。

正面案例:Stack Overflow 的架构

C# + ASP.NET + SQL Server + Redis + Elasticsearch + HAProxy,就这么简单,支撑了每月几十亿的 PV。

如何判断"简单"?

问题简单复杂
新人多久能看懂?1-2 周1-3 个月
改一个小功能要改几处?1-3 处10+ 处
排查问题跨多少系统?1-3 个10+ 个
技术栈有几种?2-5 种10+ 种

如果你用一张 A4 纸画不清楚系统架构,那可能太复杂了。


原则三:演化原则

演化优于一步到位。

架构是演化出来的,不是一开始就设计完美的。不要试图预测未来所有可能性,等问题真正出现时,再做相应的架构调整。

原因:

  1. 未来不可预测 -- 不知道业务方向、用户量、会遇到什么问题
  2. 提前设计成本高 -- 可能设计了用不上的功能,甚至方向都是错的
  3. 等问题出现再解决更准确 -- 问题清晰了方案才能对症下药

经典案例:淘宝架构演进

阶段时间规模问题方案
PHP 时代2003-2004刚起步--LAMP 单体
Java 时代2004-2007快速增长PHP 性能瓶颈迁移 Java,引入 MVC
分布式时代2007-2009千万级用户单体太大、DB 瓶颈服务化 + 分库分表
异地多活2009-2013亿级用户单机房风险跨城容灾
中台时代2013-至今几十个业务线重复建设能力复用

如果 2003 年就按 2023 年的架构设计,淘宝可能早就死了。每一次演进,都是遇到真实问题后的解决方案。

如何判断"该演进了"?

信号说明
性能瓶颈响应时间变慢、QPS 上不去
可用性问题经常宕机、故障恢复慢
团队协作困难代码冲突多、部署相互阻塞
维护成本高改一个小功能要改很多地方
扩容困难加机器效果不明显

当前架构已经成为业务发展的瓶颈,而不是支撑。


三原则小结

原则核心思想关键词
合适原则合适优于业界领先匹配业务、团队、资源
简单原则简单优于复杂KISS、易理解、易维护
演化原则演化优于一步到位迭代、按需、不预测未来
合适原则 -> 告诉你选什么方向
简单原则 -> 告诉你选什么方案
演化原则 -> 告诉你什么时候做

三、架构设计四步法

第一步:识别复杂度

第二步:设计备选方案

第三步:评估和选择

第四步:细化和落地

第一步:识别复杂度

架构设计的第一步,是识别系统的核心复杂度在哪里。这是最重要的一步。

反面案例

某内部管理系统(100 人、最多 10 并发、上班时间能用就行),团队花了三个月设计分库分表 + 读写分离 + 异地多活 + 微服务。 真正的问题(业务逻辑复杂)反而没解决好。

没有识别真正的复杂度。核心复杂度是业务逻辑复杂,不是高性能、高可用。

如何识别复杂度?

步骤 1:明确系统的核心功能

  • 这个系统是做什么的?
  • 最核心的功能是什么?
  • 用户最关心什么?

步骤 2:对照三大复杂度来源逐个分析

复杂度分析问题
高性能预期 QPS?响应时间?数据量?是否有高并发场景?
高可用可用性要求?宕机影响?是否需要 7x24?
可扩展未来功能变化?团队扩大?用户量增长?

步骤 3:确定核心复杂度

通常一个系统会有 1-2 个核心复杂度,不会全都有。

复杂度识别模板

【系统名称】:_________________

【核心功能】:
1. _________________
2. _________________

【高性能分析】:
- 预期 QPS:_______
- 响应时间要求:_______ ms
- 高性能复杂度等级:低 / 中 / 高

【高可用分析】:
- 可用性要求:_______ %
- 宕机影响:_________________
- 高可用复杂度等级:低 / 中 / 高

【可扩展分析】:
- 未来 1 年变化预期:_______
- 可扩展复杂度等级:低 / 中 / 高

【核心复杂度结论】:
主要复杂度:_________________
次要复杂度:_________________

常见复杂度判断标准

复杂度
性能QPS < 10001000-10000QPS > 10000
可用性< 99%99%-99.9%> 99.9%
数据量< 100 万100 万-1 亿> 1 亿
团队< 5 人5-20 人> 20 人

第二步:设计备选方案

针对核心复杂度,设计 3-5 个备选方案。

为什么要多个方案?

  1. 避免思维定式 -- 只想一个方案容易陷入局部最优
  2. 便于评估决策 -- 有对比才能看出优劣
  3. 降低风险 -- 首选方案有问题还有备选

方案设计的要点

要点 1:方案要有差异性

不是同一方案的不同配置,而是本质不同的方案。

要点 2:方案要覆盖不同取向

性能优先、可用性优先、简单性优先、成本优先,覆盖不同维度。

要点 3:方案要可落地

考虑团队能力、时间约束、资源是否充足。

备选方案模板

【方案名称】:_________________
【方案概述】:一句话描述
【核心思路】:1. ___  2. ___  3. ___
【关键技术】:___
【优点】:1. ___  2. ___
【缺点】:1. ___  2. ___
【风险】:___
【适用场景】:___

实战案例:秒杀系统备选方案

核心复杂度:高性能(瞬时高并发)

方案 A:纯数据库方案

用户 → Nginx → 应用服务器 → MySQL

优点:架构简单、数据一致性好、开发成本低
缺点:性能差、数据库容易成为瓶颈
适用:QPS < 1000 的小规模活动

方案 B:缓存 + 数据库方案

用户 → Nginx → 应用服务器 → Redis(扣库存)→ MySQL(异步创建订单)

优点:性能高(Redis 单机 10 万 QPS)、架构相对简单
缺点:缓存和数据库一致性问题、Redis 宕机风险
适用:QPS 1000-10 万的中等规模

方案 C:缓存 + 消息队列方案

用户 → Nginx → 应用服务器 → Redis(扣库存)→ 消息队列 → 消费者 → MySQL

优点:性能极高、削峰效果好、数据库压力小
缺点:架构复杂、用户体验变异步、需处理消息丢失/重复消费
适用:QPS > 10 万的大规模活动

方案 D:分层过滤方案

用户 → CDN → Nginx(限流)→ 应用(校验)→ Redis → 消息队列 → MySQL

优点:性能最高、层层保护后端
缺点:架构最复杂、各层需协调
适用:QPS > 100 万的超大规模

第三步:评估和选择

用多个维度评估备选方案,选出最合适的方案。

评估维度

维度说明
性能能否满足 QPS、响应时间要求
可用性故障概率、恢复时间
可扩展性加机器、加功能是否方便
成本开发成本、运维成本、硬件成本
复杂度团队能否驾驭、新人学习成本

评估方法:360 度环评

步骤 1:确定权重(秒杀系统示例)

  • 性能 30%(最重要)
  • 可用性 20%
  • 成本 20%
  • 复杂度 20%
  • 可扩展性 10%

步骤 2:打分(1-5 分)

方案性能可用性成本复杂度可扩展性
方案 A24552
方案 B43443
方案 C53334
方案 D54225

步骤 3:计算加权得分

方案加权总分
方案 A3.6
方案 B3.7
方案 C3.7
方案 D3.6

步骤 4:综合分析

光看分数还不够,还要考虑团队能力、时间约束、风险偏好、未来演进性。

实战案例:秒杀系统方案选择

背景: 团队 5 人、时间 2 个月、QPS 预期 5 万、有 Redis 经验无消息队列经验。

方案加权得分团队能力时间结论
方案 A3.6能做性能不够
方案 B3.7能做推荐
方案 C3.7缺经验不够风险高
方案 D3.6太复杂不够过度设计

选择方案 B:性能满足、团队有经验、2 个月可完成、后续可演进到方案 C。

决策原则

  1. 优先满足核心需求 -- 核心复杂度是性能就优先性能
  2. 分数接近选简单方案 -- 简单方案风险更低
  3. 考虑演进性 -- 不要选到死胡同
  4. 考虑团队能力 -- 不要高估团队能力

第四步:细化和落地

将选定的方案细化,输出可执行的设计文档。

细化的内容

内容说明
系统架构图组件、关系、数据流、关键接口
技术选型语言、框架、数据库、缓存、消息队列
数据设计表结构、缓存数据结构、分片策略
接口设计服务间接口、对外接口、协议
容量规划服务器数量、DB 配置、缓存容量
高可用设计故障应对、降级、限流、熔断
监控报警监控指标、报警阈值、应急预案
灰度方案灰度发布、回滚策略

架构设计文档模板

markdown
# XXX 系统架构设计文档

## 1. 背景
### 1.1 业务背景
### 1.2 技术背景

## 2. 需求分析
### 2.1 功能需求
### 2.2 非功能需求(性能、可用性、数据量)

## 3. 复杂度分析
### 3.1 高性能分析
### 3.2 高可用分析
### 3.3 可扩展分析
### 3.4 复杂度结论

## 4. 备选方案
### 4.1 方案一(描述、优缺点)
### 4.2 方案二
### 4.3 方案三

## 5. 方案评估
### 5.1 评估维度与权重
### 5.2 评估打分
### 5.3 方案选择与理由

## 6. 详细设计
### 6.1 系统架构图
### 6.2 技术选型
### 6.3 数据设计
### 6.4 接口设计
### 6.5 容量规划

## 7. 高可用设计
### 7.1 故障分析(FMEA)
### 7.2 降级方案
### 7.3 限流方案

## 8. 监控报警
## 9. 部署方案(灰度、回滚)
## 10. 风险与应对
## 11. 里程碑计划

四、四步法完整案例:消息队列架构设计

背景

某电商公司要自研消息队列中间件,用于内部系统解耦和异步处理。日消息量 1000 万条,消息大小 1KB 左右。

第一步:识别复杂度

复杂度分析等级
高性能峰值 1200 QPS,不算高
高可用消息不能丢,可用性 99.9%中(核心)
可扩展未来可能接入更多系统、消息量增长 10 倍

核心复杂度:高可用(消息不能丢)

第二步:设计备选方案

方案 A:MySQL 消息表

生产者 → MySQL(消息表)← 消费者(轮询)

优点:实现简单、消息持久化不丢失
缺点:性能一般、轮询效率低

方案 B:Redis List

生产者 → Redis List ← 消费者(BLPOP)

优点:性能高、实现简单
缺点:Redis 宕机消息可能丢失、不支持消息确认

方案 C:自研仿 Kafka

生产者 → Broker 集群(磁盘持久化)← 消费者

优点:高性能、高可用(副本)、可扩展(分区)
缺点:实现复杂、开发周期长

第三步:评估和选择

权重:可用性 30%、性能 20%、复杂度 25%、可扩展 15%、成本 10%

方案加权得分核心问题
方案 A3.45性能一般但满足可用性
方案 B3.60可用性差、消息可能丢失
方案 C3.75得分最高但实现复杂

选择方案 A(MySQL 方案)

理由:满足核心需求(消息不丢)、实现简单风险低、2 个月可完成、后续可演进到方案 C。

第四步:细化

sql
CREATE TABLE mq_message (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    topic VARCHAR(128) NOT NULL,
    msg_key VARCHAR(128) NOT NULL,
    msg_body TEXT NOT NULL,
    status TINYINT NOT NULL DEFAULT 0 COMMENT '0-待消费 1-已消费',
    retry_count INT NOT NULL DEFAULT 0,
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    INDEX idx_topic_status (topic, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

高可用:MySQL 主从复制、消息重试机制、死信队列、监控报警。


五、面试高频题

Q1:架构设计有哪些原则?

三大原则:合适原则(合适优于业界领先,匹配业务规模和团队能力)、简单原则(简单优于复杂,KISS)、演化原则(演化优于一步到位,遇到问题再演进)。

Q2:你是怎么做架构设计的?

四步法:1) 识别核心复杂度(高性能/高可用/可扩展);2) 设计 3-5 个有差异性的备选方案;3) 多维度评估(性能、可用性、成本、复杂度),综合考虑团队能力;4) 细化落地,输出设计文档。

Q3:如何判断一个架构方案好不好?

从五个维度:是否解决核心问题、是否满足质量要求(性能/可用性/可扩展)、是否合适(匹配团队能力和资源约束)、是否简单(容易理解和维护)、是否可演进(便于后续升级)。

Q4:你做过的架构方案是怎么选型的?

用 STAR 法:Situation(背景规模)→ Task(核心复杂度)→ Action(设计 3 个方案、评估选择)→ Result(上线效果、经验教训)。

Q5:如何避免过度设计?

遵循三原则:1) 问自己"是当前需要还是未来可能需要",未来可能需要的先不做;2) 问自己"有没有更简单的方案";3) 问自己"这个问题现在必须解决吗"。具体方法:先做最小可行架构、用数据说话、让团队挑战你的设计。


六、练习题

练习 1:原则应用

判断以下场景违反了哪个原则:

场景 A: 3 人团队、日活 500,使用微服务架构拆分 15 个服务。

场景 B: 只在中国运营,一开始就做完整的多语言、多时区、多货币支持。

场景 C: 消息量每天 1 万条,因为竞品用了 Kafka 就决定也用 Kafka。

练习 2:复杂度识别

分析以下系统的核心复杂度:

系统 A: 在线考试系统 -- 10 万学生、1 万人同时在线、不能宕机、成绩不能错。

系统 B: 内部 OA 系统 -- 500 员工、日常办公、上班时间能用就行。

系统 C: 电商推荐系统 -- 1000 万用户、实时推荐、< 100ms。

练习 3:方案设计

为短链接服务设计 3 个备选方案:日均新增 100 万短链接、日均访问 1 亿次、短链接永久有效。

练习 4:架构文档

选择一个你熟悉的系统,按照本讲的架构设计文档模板,写一份简化版文档(至少包含背景、复杂度分析、备选方案、方案选择、系统架构图)。


下一讲预告

第 3 讲:高性能架构模式(上)-- 单机高性能

  • I/O 模型:PPC、TPC、Reactor、Proactor
  • Reactor 的三种变体
  • Nginx、Redis、Netty 的 I/O 模型分析
  • 各模型的适用场景和选型建议

基于 VitePress 构建