原则:能写代码的人很多,能设计系统的人很少。 高并发设计 + DDD 领域建模 + 技术方案评审 = 高级工程师的核心竞争力。


一、高并发系统设计(★★★★★)

1.1 秒杀系统完整方案

秒杀系统的核心矛盾:极少量库存 vs 海量并发请求

设计分层(从前到后):
┌─────────────────────────────────────────────┐
│ 第 1 层:前端限流                             │
│ ├── 按钮置灰(点击后 5 秒内不可再点)            │
│ └── 验证码/滑块(过滤脚本和机器请求)            │
├─────────────────────────────────────────────┤
│ 第 2 层:网关限流                             │
│ ├── Nginx 限流(limit_req_zone)             │
│ └── Gateway 令牌桶限流(Sentinel)             │
├─────────────────────────────────────────────┤
│ 第 3 层:应用层                               │
│ ├── Redis 预减库存(Lua 脚本原子操作)          │
│ ├── 内存标记(商品售罄后不再查 Redis)          │
│ └── 消息队列异步下单(削峰填谷)               │
├─────────────────────────────────────────────┤
│ 第 4 层:数据库层                             │
│ └── 最终扣减库存(UPDATE ... WHERE stock > 0)  │
├─────────────────────────────────────────────┤
│ 辅助措施:                                    │
│ ├── CDN 静态化(商品详情页提前静态化)          │
│ ├── Redis 缓存预热(秒杀开始前加载库存到 Redis) │
│ ├── 隔离部署(秒杀服务独立部署,不影响主流程)    │
│ └── 降级预案(秒杀失败降级为排队等待)          │
└─────────────────────────────────────────────┘

1.2 库存扣减方案对比

方案 A:Redis 扣减 → MQ 异步同步到 DB
  优点:性能最高
  缺点:Redis 和 DB 数据可能不一致

方案 B:数据库直接扣减(UPDATE ... WHERE stock > 0)
  优点:数据强一致
  缺点:数据库压力大

方案 C:Redis Lua 原子扣减 + DB 最终扣减(推荐)
  1. 秒杀开始前:预热库存到 Redis
  2. 秒杀中:Redis Lua 脚本原子扣减
  3. 秒杀后:MQ 异步同步到 DB,DB 做最终一致性兜底

1.3 性能优化三层模型

┌──────────┬──────────────────────────────┐
│ 层级     │ 优化手段                       │
├──────────┼──────────────────────────────┤
│ 代码层   │ 减少循环嵌套、异步并行、连接池   │
│          │ N+1 问题、Stream 并行流         │
├──────────┼──────────────────────────────┤
│ 缓存层   │ Redis 热数据缓存、本地缓存       │
│          │ Caffeine、多级缓存              │
├──────────┼──────────────────────────────┤
│ 数据库层 │ 索引优化、SQL 优化、读写分离      │
│          │ 分库分表、连接池配置              │
└──────────┴──────────────────────────────┘

优化思路:永远从最上层开始,缓存能解决的不要动数据库,
        代码能解决的不要加机器。

二、高可用架构设计

2.1 可用性保障手段

1. 冗余部署:多实例 + 多机房(消除单点故障)
2. 故障转移:健康检查 + 自动摘除故障节点
3. 超时控制:调用下游设置合理超时,避免级联阻塞
4. 重试机制:幂等 + 退避策略(指数退避,最大重试次数)
5. 服务降级:非核心功能自动关闭(如推荐系统故障降级为热门推荐)
6. 熔断:慢调用/异常比例超过阈值 → 快速失败
7. 限流:令牌桶/漏桶,保护系统不被突发流量打垮
8. 容灾:异地多活/两地三中心

2.2 可用性指标

等级全年不可用时间可用性
3 个 9< 8.76 小时99.9%
4 个 9< 52.6 分钟99.99%
5 个 9< 5.26 分钟99.999%

4 个 9 是大多数互联网公司的目标。


三、DDD 领域驱动设计(★★★★☆)

3.1 核心概念

战略设计(宏观):
- 限界上下文(Bounded Context):业务边界,微服务拆分的依据
- 上下文映射(Context Map):限界上下文之间的关系
  - 共享内核(Shared Kernel)
  - 客户-供应商(Customer-Supplier)
  - 防腐层(Anti-Corruption Layer)
  - 开放主机服务(Open Host Service)

战术设计(微观):
- 聚合根(Aggregate Root):聚合的唯一入口,保证业务规则
- 实体(Entity):有唯一标识,可变
- 值对象(Value Object):无标识,不可变(如金额、地址)
- 领域服务(Domain Service):跨聚合的业务逻辑
- 仓储(Repository):聚合的持久化接口
- 领域事件(Domain Event):领域中发生的有意义的事件

3.2 电商系统 DDD 建模示例

限界上下文划分:
┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
│ 用户上下文 │  │ 订单上下文 │  │ 商品上下文 │  │ 支付上下文 │
│ User     │  │ Order    │  │ Product  │  │ Payment  │
└──────────┘  └──────────┘  └──────────┘  └──────────┘

订单上下文内部(聚合设计):
Order(聚合根)
├── OrderItem(实体,订单项)
├── OrderAddress(值对象,收货地址)
└── OrderEvent(领域事件,订单已创建/已支付/已发货)

关键规则:
- 外部只能通过聚合根操作聚合内部实体
- 一个事务只修改一个聚合
- 聚合之间通过领域事件异步通信

四、技术方案评审

4.1 方案文档结构

# [项目名称] 技术方案

## 1. 需求背景
- 业务痛点
- 核心指标(QPS/响应时间/数据量)

## 2. 方案对比
| 方案 | 优点 | 缺点 | 风险 |
|------|------|------|------|
| 方案 A | ... | ... | ... |
| 方案 B | ... | ... | ... |
| 推荐方案:方案 X,理由:...

## 3. 详细设计
- 系统架构图(用 draw.io 或 PlantUML)
- 核心流程图/时序图
- 数据库表设计(ER 图)
- 接口定义(请求/响应格式)

## 4. 关键决策
| 决策点 | 选项 | 选择 | 理由 |
|--------|------|------|------|

## 5. 风险评估
| 风险 | 概率 | 影响 | 应对措施 |
|------|------|------|---------|

## 6. 上线计划
- 灰度策略
- 监控告警
- 回滚方案

4.2 评审发言框架

当别人评审你的方案时:
1. 讲背景,不讲细节:"这个问题的本质是..."
2. 讲权衡,不讲完美:"方案 A 更快但一致性弱,方案 B 一致但慢"
3. 讲风险,不讲理想:"最坏情况下可能发生..."
4. 讲数据,不讲感觉:"压测数据显示 QPS 从 1000 提升到 3000"

当你评审别人的方案时:
1. 先理解业务需求,再评价技术方案
2. 提问代替结论:"这里考虑过 XX 情况吗?"
3. 关注边界条件和异常路径
4. 给建设性建议,不只说"不好"

面试自查清单

□ 秒杀系统的 4 层架构能画出来(前端→网关→应用→数据库)
□ 库存扣减 3 种方案的优缺点和选型依据
□ 4 个 9 可用性 = 全年不可用 < 52.6 分钟
□ DDD 聚合根、实体、值对象的区别 + 仓储的作用
□ 上下文映射的 4 种关系能各举例一个
□ 技术方案文档的标准结构(6 部分)
□ 性能优化的三层模型(代码→缓存→数据库)