04 - 架构与设计:技术决策 → 系统蓝图
架构决策 = 不可逆决策。错了一次,要花 10 倍代价回头改。所以 ADR 不是给"已经定了"的决策用的,是给"还没定"时用的。
一句话
架构师的核心产出 = ADR + 架构图 + 接口契约 + 数据模型——四件套把"模糊的技术决策"变成"团队共识的可执行蓝图"。
架构师的 3 大产出
无论什么项目,架构师必交付这 3 件:
产出 1:架构决策记录(ADR)
为什么必须写:
- 6 个月后你不在了,新人不知道为什么选 PostgreSQL
- 重要决策被遗忘,下个人提同样的问题
- 没有 ADR = 没有"决策历史"= 组织失忆
ADR 模板(基于 MADR):
# ADR-2026-Q3-001:选择 PostgreSQL 作为主数据库
## 状态
2026-06-28 已接受
## 背景和约束
- 当前 5 万行日活用户
- 需要事务 + 全文搜索 + JSONB
- 团队有 PG 经验,无 MongoDB 经验
- 预算有限,希望不开新组件
## 备选方案
### 选项 A:MySQL 8.0 + Elasticsearch
- 优点:团队熟悉 MySQL;ES 搜索强
- 缺点:两个组件,运维成本高;事务需要同步双写
- 评估:维护成本 +1,延期风险高
### 选项 B:MongoDB
- 优点:天然支持 JSON;水平扩展容易
- 缺点:团队无经验;事务能力弱(4.0 前)
- 评估:学习曲线陡,3 个月内不可用
### 选项 C:PostgreSQL 14+
- 优点:单组件;全文搜索原生支持;JSONB 完善
- 缺点:水平扩展需要额外工具(Citus)
- 评估:MVP 期足够,未来可加 Citus
## 决策
**选择 C:PostgreSQL 14+**
## 影响
- + 数据库单一组件,运维简单
- + 团队立即上手
- - 未来扩展需要评估 Citus 或分库
- - 需要 DBA 或团队培训
## 决策时间
2026-06-28
## 决策人
张三(架构师)+ 李四(技术负责人)+ 王五(运维负责人)ADR 必须有的 5 部分:
- 状态(提议 / 已接受 / 已废弃 / 已取代)
- 背景(为什么需要决策)
- 选项(至少 2 个,含优缺点)
- 决策(明确选哪个)
- 影响(正负两面)
什么时候写 ADR:
- ✅ 选数据库 / 消息队列 / 框架
- ✅ 选架构风格(微服务 / 单体 / 事件驱动)
- ✅ 接口设计(REST vs GraphQL vs gRPC)
- ✅ 数据建模关键决策(如订单的状态机)
- ❌ 一行代码的写法
- ❌ 测试用例
产出 2:架构图(C4 模型)
Simon Brown 的 C4 模型——4 层抽象:
Level 1: System Context(系统上下文)
↓ 整个系统在一个图里
Level 2: Container(容器)
↓ 进程/服务/数据库
Level 3: Component(组件)
↓ 类/模块/包
Level 4: Code(代码)
↓ 类图/ER 图(可选)Level 1 示例(用户视角):
┌─────────────────────────────────────────────┐
│ 电商系统 │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ 用户 Web/App │ │ 商家后台 │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ [核心电商系统] │ │
│ │ 订单 · 商品 · 支付 · 履约 │ │
│ └────────────┬────────────────────┘ │
│ │ │
└─────────────────┼───────────────────────────────┘
▼
┌─────────────────────┐
│ 第三方:支付/物流 │
└─────────────────────┘Level 2 示例(技术视角):
┌──────────────────────────────────────────────┐
│ Web App (React) │
│ Mobile App (RN) │
└──────────────────┬───────────────────────────────┘
│ HTTPS
▼
┌──────────────────────────────────────────────┐
│ API Gateway (Kong) │
└────┬──────────────┬──────────────┬─────────────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 订单服务 │ │ 商品服务 │ │ 支付服务 │
│ (Java) │ │ (Python) │ │ (Go) │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 订单 DB │ │ 商品 DB │ │ 支付 DB │
│ (PG) │ │ (ES) │ │ (PG) │
└──────────┘ └──────────┘ └──────────┘产出 3:接口契约(API Contract)
REST API 必须包含:
openapi: 3.0.0
info:
title: 订单 API
version: 1.0.0
paths:
/orders:
post:
summary: 创建订单
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
responses:
'201':
description: 成功
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
description: 参数错误
'409':
description: 库存不足
components:
schemas:
CreateOrderRequest:
type: object
required:
- user_id
- items
properties:
user_id:
type: string
items:
type: array
items:
type: object
properties:
product_id:
type: string
quantity:
type: integer事件契约(Event Contract):
{
"event_type": "order.created",
"version": "1.0",
"data": {
"order_id": "uuid",
"user_id": "uuid",
"items": [...],
"total": 99.99,
"currency": "CNY",
"created_at": "2026-06-28T12:00:00Z"
}
}架构设计的 7 步法
Step 1:业务问题映射
输入:立项书 + 用户故事 输出:业务能力图(哪些能力必须支持)
Step 2:领域划分(DDD Bounded Context)
用 IDDD L3 BC 范式:
- 一个 BC = 一个明确的业务边界
- BC 间不能直接改对方数据库
- BC 间只能通过 API / 事件通信
判断标志:
- 这个概念在这个 BC 和另一个 BC 含义不同时 → 拆 BC
- 团队规模到 5+ 个 → 拆 BC
- 部署可以独立 → 拆 BC
Step 3:选架构风格
决策矩阵:
| 场景 | 推荐架构 |
|---|---|
| 简单业务 + 团队 < 5 人 | 单体(不是 monorepo,是单 deployable) |
| 业务多 + 团队 5-30 人 | 微服务 |
| 高并发读写冲突 | CQRS |
| 数据量大 + 解耦 | 事件驱动 |
| 跨学科系统 | 六边形 + SOA |
Vernon Ch4 警告:
"Architectural styles are not a grab bag of cool tools... use them only where applicable."
Step 4:技术栈选型
技术雷达(ThoughtWorks)模型:
采纳(Adopt): 团队所有人都用,主力技术
试用(Trial): 局部场景使用,有 1-2 个团队用
评估(Assess): 值得研究,1 个团队在评估
暂缓(Hold): 不推荐新项目使用,但旧项目还在用示例:
采纳: TypeScript、React、PostgreSQL、Kafka
试用: Rust、Deno、ClickHouse、eBPF
评估: WebAssembly、WASM Components
暂缓: MongoDB(除非特殊场景)、SOAPStep 5:数据建模
ER 图关键问题:
- 哪些是实体(独立存在)?
- 哪些是值对象(依附实体,无独立标识)?
- 哪些是聚合(一组相关对象)?
- 聚合的边界在哪(写边界)?
Idempotency(幂等性):所有写操作必须有 idempotency_key,防止重复请求导致问题。
Step 6:接口设计
REST:
- 资源用名词,不用动词
- 状态用 HTTP status code
- 不要把内部表结构暴露给 API
事件:
- 事件名用过去时(OrderCreated 不是 CreateOrder)
- Schema 必填字段 + 可选字段
- 版本字段必须
Step 7:非功能性需求
必答 6 个:
- 性能——并发多少?响应时间要求?
- 可用性——SLA 多少(99.9% / 99.99%)?
- 可扩展性——业务量 10 倍怎么应对?
- 安全性——数据脱敏?加密传输?
- 可观测性——日志 / 指标 / 追踪?
- 可维护性——团队扩大 2 倍还能维护吗?
跨团队改动(LSC,Large-Scale Changes)
SE@Google Ch22 的核心观点:
"Large-Scale Changes can touch hundreds of CLs across many codebases."
LSC 的 4 步流程:
1. 设计:找所有受影响团队 + 设计协调员
↓
2. 共识:RFC 在所有团队评审通过
↓
3. 执行:分阶段 5% → 50% → 100%
↓
4. 收尾:清理旧代码 + 文档更新协调员(Coordinator)必备:
- 一个明确的人推这件事
- 不是大家各改各的
- 协调员必须有权决定"什么时候强制执行"
反模式:没有协调员的 LSC = 5 个团队改了 5 个版本,互相不兼容。
设计的反模式(5 种)
1. 过度设计
症状:5 人团队设计 30 个微服务 + 6 种存储 + 4 种消息队列
修复:YAGNI(You Aren't Gonna Need It)——先简单,跑通业务再考虑拆分。
2. 设计脱离业务
症状:架构师沉迷技术选型,半年后业务没进展
修复:每个技术决策挂到业务结果上。
3. 不写 ADR,靠口头传承
症状:架构师离职带走所有"为什么"的知识
修复:每个重要决策写 ADR。新人 onboard 第一周读所有 ADR。
4. 复制大厂架构
症状:5 万用户系统套用 Google 十万级工程师架构
修复:架构匹配业务规模——参考 SE@Google Ch1"trade-offs"。
5. 设计完不评审
症状:架构师一个人做完设计,团队不知道
修复:架构评审会(Architecture Review)——邀请所有人评审,特别是被影响的团队。
架构评审会
议程:
1. 业务背景(5 分钟)
2. 当前架构痛点(5 分钟)
3. 提议架构(10 分钟)
4. 备选方案对比(10 分钟)
5. Q&A + 风险讨论(20 分钟)
6. 决策(5 分钟)参加人:
- 必到:架构师本人、受影响团队 Lead、SRE/运维负责人
- 选到:技术总监、跨团队代表、新人(避免信息孤岛)
架构文档库
最小集合:
architecture/
├── adr/ # ADR 列表
│ ├── 001-postgresql.md
│ ├── 002-kafka.md
│ └── 003-event-driven.md
├── diagrams/ # C4 模型图
│ ├── c1-context.png
│ ├── c2-containers.png
│ └── c3-components.png
├── api/ # API 契约
│ ├── openapi.yaml
│ └── events.json
├── data/ # 数据建模
│ ├── er-diagram.png
│ └── schema-evolution.md
├── runbooks/ # 运维手册
│ ├── deployment.md
│ └── incident-response.md
└── README.md # 索引进入下一章
架构与设计完成后,下一步:
- 05 任务与冲刺——把架构设计分解为可执行任务
作者:基于 IDDD L4 (Context Maps) + SE@Google Ch22 (LSC) + Vernon Ch4 (架构风格) 综合 最后更新:2026-06-28