跳到主要内容

07-系统设计与架构

核心理念

好的架构不是设计出来的,是演进出来的。

1x工程师: 实现功能
10x工程师: 设计良好的架构
100x工程师: 构建可演进的平台

系统设计的三个境界

境界1: 功能实现(1x)

特征:

需求 → 实现 → 交付

思维模式:

  • 关注: 功能完整性
  • 目标: 能work就行
  • 问题: 难以扩展、难以维护

典型表现:

// 所有代码都在一个文件
// 所有逻辑都在一个函数
function handleUserLogin(req, res) {
// 参数验证
// 数据库查询
// 密码验证
// Session管理
// 日志记录
// 返回响应
// ... 200行代码
}

境界2: 架构设计(10x)

特征:

需求分析 → 架构设计 → 模块划分 → 实现

思维模式:

  • 关注: 系统质量属性(性能、可维护性、可扩展性)
  • 目标: 长期可维护
  • 价值: 降低维护成本,支撑业务增长

典型架构模式:

分层架构(Layered Architecture)

┌─────────────────────┐
│ Presentation │ 表现层(API/UI)
├─────────────────────┤
│ Business Logic │ 业务逻辑层
├─────────────────────┤
│ Data Access │ 数据访问层
├─────────────────────┤
│ Database │ 数据存储层
└─────────────────────┘

优势:
- 职责清晰
- 易于理解
- 便于测试

劣势:
- 层级过多时性能损失
- 跨层依赖复杂

境界3: 平台思维(100x)

特征:

业务抽象 → 平台设计 → 能力开放 → 生态构建

思维模式:

  • 关注: 可复用性、可扩展性、生态
  • 目标: 一次建设,多次复用,赋能他人
  • 价值: 组织级影响

平台化架构:

          业务A    业务B    业务C
↓ ↓ ↓
┌──────────────────────────┐
│ 业务能力层 │
│ ┌────┐ ┌────┐ ┌────┐ │
│ │用户│ │订单│ │商品│ │
│ └────┘ └────┘ └────┘ │
├──────────────────────────┤
│ 平台能力层 │
│ ┌────┐ ┌────┐ ┌────┐ │
│ │认证│ │支付│ │消息│ │
│ └────┘ └────┘ └────┘ │
├──────────────────────────┤
│ 基础设施层 │
│ 数据库 缓存 消息队列 │
└──────────────────────────┘

特点:
- 通用能力平台化
- 业务能力可组合
- 系统高度可复用

架构设计原则

原则1: 高内聚、低耦合

高内聚: 相关功能聚集在一起

❌ 低内聚示例:
User模块包含: 用户管理、订单处理、支付逻辑

✓ 高内聚示例:
User模块: 用户CRUD、认证授权
Order模块: 订单管理
Payment模块: 支付逻辑

低耦合: 模块间依赖最小化

❌ 高耦合示例:
OrderService直接访问UserRepository
OrderService直接调用PaymentService的私有方法

✓ 低耦合示例:
OrderService通过接口依赖UserService
OrderService通过事件通知PaymentService

原则2: 单一职责原则(SRP)

定义: 一个模块只负责一件事。

// ❌ 违反SRP
class UserService {
createUser() { }
updateUser() { }
deleteUser() { }
sendEmail() { } // 邮件发送不是用户管理的职责
generateReport() { } // 报表生成不是用户管理的职责
}

// ✓ 符合SRP
class UserService {
createUser() { }
updateUser() { }
deleteUser() { }
}

class EmailService {
sendEmail() { }
}

class ReportService {
generateReport() { }
}

原则3: 开闭原则(OCP)

定义: 对扩展开放,对修改关闭。

// ❌ 违反OCP
class PaymentProcessor {
process(type) {
if (type === 'alipay') {
// 支付宝逻辑
} else if (type === 'wechat') {
// 微信逻辑
}
// 新增支付方式需要修改这里
}
}

// ✓ 符合OCP
interface PaymentMethod {
pay(amount: number): Promise<void>;
}

class AlipayPayment implements PaymentMethod {
async pay(amount: number) { /* ... */ }
}

class WechatPayment implements PaymentMethod {
async pay(amount: number) { /* ... */ }
}

class PaymentProcessor {
constructor(private method: PaymentMethod) {}

async process(amount: number) {
await this.method.pay(amount);
}
}

// 新增支付方式只需添加新类,不需要修改现有代码
class StripePayment implements PaymentMethod {
async pay(amount: number) { /* ... */ }
}

原则4: 依赖倒置原则(DIP)

定义: 依赖抽象而非具体实现。

// ❌ 依赖具体实现
class UserService {
private mysql: MySQL; // 直接依赖MySQL

constructor() {
this.mysql = new MySQL();
}

getUser(id: string) {
return this.mysql.query(`SELECT * FROM users WHERE id = ${id}`);
}
}

// ✓ 依赖抽象
interface Database {
query(sql: string): Promise<any>;
}

class MySQL implements Database {
async query(sql: string) { /* ... */ }
}

class PostgreSQL implements Database {
async query(sql: string) { /* ... */ }
}

class UserService {
constructor(private db: Database) {} // 依赖接口

getUser(id: string) {
return this.db.query(`SELECT * FROM users WHERE id = ${id}`);
}
}

// 可以灵活切换数据库
const userService = new UserService(new PostgreSQL());

常见架构模式

模式1: 分层架构(Layered Architecture)

┌──────────────────┐
│ Controller │ ← 接收请求,返回响应
├──────────────────┤
│ Service │ ← 业务逻辑
├──────────────────┤
│ Repository │ ← 数据访问
├──────────────────┤
│ Database │ ← 数据存储
└──────────────────┘

适用场景:

  • 中小型应用
  • 业务逻辑清晰
  • 团队规模小

优势:

  • 简单易懂
  • 便于测试
  • 职责清晰

示例:

// Controller层
class UserController {
constructor(private userService: UserService) {}

async createUser(req, res) {
const user = await this.userService.create(req.body);
res.json(user);
}
}

// Service层
class UserService {
constructor(private userRepo: UserRepository) {}

async create(data: UserDTO) {
// 业务逻辑验证
if (!data.email) throw new Error('Email required');

// 调用Repository
return await this.userRepo.save(data);
}
}

// Repository层
class UserRepository {
async save(data: UserDTO) {
// 数据库操作
return await db.insert('users', data);
}
}

模式2: 六边形架构(Hexagonal Architecture)

也称为"端口和适配器架构"。

        ┌─────────────┐
│ 外部系统 │
└──────┬──────┘
│ 适配器
┌──────▼──────────┐
│ Port (接口) │
├─────────────────┤
│ 核心业务逻辑 │
├─────────────────┤
│ Port (接口) │
└──────┬──────────┘
│ 适配器
┌──────▼──────┐
│ 数据库 │
└─────────────┘

核心思想: 业务逻辑独立于外部依赖。

优势:

  • 业务逻辑可独立测试
  • 易于替换外部依赖
  • 清晰的边界

示例:

// 核心业务逻辑(领域层)
class User {
constructor(
private id: string,
private email: string,
private password: string
) {}

changePassword(newPassword: string) {
// 业务规则
if (newPassword.length < 8) {
throw new Error('Password too short');
}
this.password = newPassword;
}
}

// 端口(接口)
interface UserRepository {
save(user: User): Promise<void>;
findById(id: string): Promise<User | null>;
}

interface EmailService {
send(to: string, subject: string, body: string): Promise<void>;
}

// 业务服务(应用层)
class UserService {
constructor(
private userRepo: UserRepository,
private emailService: EmailService
) {}

async changePassword(userId: string, newPassword: string) {
const user = await this.userRepo.findById(userId);
if (!user) throw new Error('User not found');

user.changePassword(newPassword);
await this.userRepo.save(user);
await this.emailService.send(
user.email,
'Password Changed',
'Your password has been changed'
);
}
}

// 适配器(基础设施层)
class MongoUserRepository implements UserRepository {
async save(user: User) {
// MongoDB实现
}
async findById(id: string) {
// MongoDB实现
}
}

class SendGridEmailService implements EmailService {
async send(to: string, subject: string, body: string) {
// SendGrid实现
}
}

// 组装
const userService = new UserService(
new MongoUserRepository(),
new SendGridEmailService()
);

模式3: 微服务架构

                  API Gateway

┌──────────────┼──────────────┐
↓ ↓ ↓
用户服务 订单服务 商品服务
↓ ↓ ↓
用户DB 订单DB 商品DB

特点:

  • 服务独立部署
  • 数据库独立
  • 技术栈可异构

适用场景:

  • 大型应用
  • 团队规模大
  • 业务复杂

优势:

  • 独立扩展
  • 技术多样性
  • 故障隔离

挑战:

  • 分布式复杂性
  • 数据一致性
  • 服务治理

可扩展性设计

维度1: 垂直扩展(Scale Up)

定义: 增加单个服务器的资源(CPU、内存)。

单机 4核8G

单机 16核32G

单机 64核128G

优势:

  • 简单直接
  • 无需改代码

局限:

  • 有物理上限
  • 成本指数增长
  • 单点故障风险

维度2: 水平扩展(Scale Out)

定义: 增加服务器数量。

1台服务器

3台服务器(负载均衡)

10台服务器(分布式)

优势:

  • 理论无上限
  • 成本线性增长
  • 高可用

设计要点:

1. 无状态服务

// ❌ 有状态(无法水平扩展)
let requestCount = 0;

app.get('/api', (req, res) => {
requestCount++; // 状态存在内存中
res.json({ count: requestCount });
});

// ✓ 无状态(可水平扩展)
app.get('/api', async (req, res) => {
const count = await redis.incr('request_count'); // 状态存储在外部
res.json({ count });
});

2. 负载均衡

           Load Balancer

┌─────────┼─────────┐
↓ ↓ ↓
Server1 Server2 Server3

常见算法:

  • Round Robin: 轮询
  • Least Connections: 最少连接
  • IP Hash: IP哈希(会话保持)

3. 数据分片(Sharding)

用户数据

Hash(user_id) % 3

Shard 0: user 0, 3, 6, 9...
Shard 1: user 1, 4, 7, 10...
Shard 2: user 2, 5, 8, 11...

高可用设计

策略1: 冗余

单点消除:

❌ 单点故障:
App → DB → 如果DB挂了,整个系统不可用

✓ 主从复制:
┌→ DB Master (读写)
App → ─┤
└→ DB Slave (只读)

✓ 多主复制:
┌→ DB Master 1 ←─┐
App ─┤ │ 双向复制
└→ DB Master 2 ←─┘

策略2: 熔断

防止雪崩效应:

class CircuitBreaker {
private failureCount = 0;
private lastFailureTime = 0;
private state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN

async call(fn: Function) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailureTime > 60000) {
this.state = 'HALF_OPEN';
} else {
throw new Error('Circuit breaker is OPEN');
}
}

try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}

private onSuccess() {
this.failureCount = 0;
this.state = 'CLOSED';
}

private onFailure() {
this.failureCount++;
this.lastFailureTime = Date.now();

if (this.failureCount >= 5) {
this.state = 'OPEN';
}
}
}

// 使用
const breaker = new CircuitBreaker();
await breaker.call(() => externalAPI.call());

策略3: 限流

保护系统不被压垮:

// 令牌桶算法
class RateLimiter {
private tokens: number;
private lastRefillTime: number;

constructor(
private capacity: number, // 桶容量
private refillRate: number // 每秒补充的令牌数
) {
this.tokens = capacity;
this.lastRefillTime = Date.now();
}

async acquire(): Promise<boolean> {
this.refill();

if (this.tokens >= 1) {
this.tokens -= 1;
return true;
}

return false;
}

private refill() {
const now = Date.now();
const timePassed = (now - this.lastRefillTime) / 1000;
const tokensToAdd = timePassed * this.refillRate;

this.tokens = Math.min(this.capacity, this.tokens + tokensToAdd);
this.lastRefillTime = now;
}
}

// 使用
const limiter = new RateLimiter(100, 10); // 容量100,每秒补充10个

app.get('/api', async (req, res) => {
if (!await limiter.acquire()) {
return res.status(429).send('Too Many Requests');
}

// 处理请求
});

演进式架构

核心思想

不要大爆炸重写,要渐进式演进。

❌ 大爆炸重写:
老系统 → 停止开发 → 重写3个月 → 切换 → 失败风险高

✓ 渐进式演进:
老系统 → 逐步抽取模块 → 新老共存 → 逐步迁移 → 风险可控

演进策略

策略1: 绞杀者模式(Strangler Pattern)

阶段1: 新老系统共存
Router

┌────┴────┐
↓ ↓
新系统A 老系统
(10%流量) (90%流量)

阶段2: 逐步迁移
Router

┌────┴────┐
↓ ↓
新系统A+B 老系统
(50%流量) (50%流量)

阶段3: 完全迁移
新系统A+B+C
(100%流量)

老系统下线

策略2: 分支抽象(Branch by Abstraction)

// 步骤1: 创建抽象层
interface PaymentService {
pay(amount: number): Promise<void>;
}

// 步骤2: 老实现适配抽象
class OldPaymentService implements PaymentService {
async pay(amount: number) {
// 老逻辑
}
}

// 步骤3: 新实现
class NewPaymentService implements PaymentService {
async pay(amount: number) {
// 新逻辑
}
}

// 步骤4: 功能开关控制
class PaymentServiceFactory {
static create(): PaymentService {
if (featureFlag.isEnabled('new_payment')) {
return new NewPaymentService();
}
return new OldPaymentService();
}
}

// 使用
const paymentService = PaymentServiceFactory.create();
await paymentService.pay(100);

// 步骤5: 逐步切换 → 完全切换 → 删除老代码

架构决策记录(ADR)

为什么需要ADR

问题: 6个月后,没人记得为什么这样设计。

解决: 记录重要的架构决策。

ADR模板

# ADR-001: 使用PostgreSQL作为主数据库

## 状态
已采纳 (Accepted)

## 背景
我们需要选择一个关系型数据库来存储用户和订单数据。

## 决策
选择PostgreSQL作为主数据库。

## 理由
1. 支持JSON类型,灵活性好
2. 支持全文搜索
3. 社区活跃,生态成熟
4. 团队有使用经验
5. 开源免费

## 备选方案
- MySQL: 更流行,但JSON支持较弱
- MongoDB: 灵活性最好,但缺少事务支持

## 后果
### 正面影响
- 支持复杂查询
- 数据一致性强

### 负面影响
- 学习曲线比MySQL陡
- 性能调优需要经验

## 相关决策
- ADR-002: 使用Redis作为缓存

## 更新记录
- 2025-12-01: 初始决策

架构设计实践清单

需求阶段

  • 明确功能需求和非功能需求
  • 识别核心业务流程
  • 估算规模(用户数、数据量、QPS)
  • 明确约束条件(预算、时间、技术栈)

设计阶段

  • 选择合适的架构模式
  • 模块划分和职责定义
  • 定义接口和数据模型
  • 识别风险点

评审阶段

  • 可行性评估
  • 性能评估
  • 可扩展性评估
  • 成本评估
  • 记录ADR

实施阶段

  • MVP优先
  • 增量开发
  • 持续集成
  • 监控和日志

演进阶段

  • 收集反馈
  • 性能优化
  • 架构重构
  • 技术债偿还

关键要点总结

  1. 演进思维: 架构是演进的,不是一次设计完美
  2. 权衡取舍: 没有最好的架构,只有最合适的
  3. 简单优先: 从简单开始,需要时再复杂化
  4. 文档化: 记录重要的架构决策(ADR)
  5. 可测试性: 好的架构是易于测试的

核心公式:

好架构 = 满足需求 + 可扩展 + 可维护 + 合理成本
100x架构 = 平台化思维 + 演进能力 + 生态赋能

← 上一章:团队与领导力 | 下一章:实践路径图 →