系统设计 101

Posted by LiYixian on Thursday, January 1, 2026 | 阅读 | ,阅读约 4 分钟

系统设计框架

  1. 弄清具体要求
    1. 功能需求
      1. 考虑最重要的三个功能
    2. 非功能需求
      1. 一些基本的取舍(trade-offs)
  2. 核心 entities
    1. 系统中的参与者有哪些?满足功能需求需要什么资源?
  3. 高层架构
    1. 用方框和箭头表示系统的不同组件及其交互方式
    2. 组件:基本技术模块,例如服务器、数据库、缓存等
    3. 数据如何在系统中流动,以及每次请求(从 API 请求到响应)都会改变哪些状态
  4. API /接口
    1. 使用哪种协议(外部 API 用 REST,内部调用用 gRPC)
  5. 深挖,一些独立的问题
    1. 非功能需求
    2. 极端情况和瓶颈

非功能需求

  • 一致性
    • 强一致性 (Strong Consistency):任何时候读到的都是最新写入的数据
    • 最终一致性 (Eventual Consistency): 允许短时间内数据不一致,但最终会同步
      • 分布式事务:一个操作跨越多个数据库/服务时,如何处理?
  • 可用性
    • 系统能否一直在线,挂了怎么办?
  • 实时性
    • 响应有多快,延迟是多少?
  • 扩展性
    • 用户从 1 万增长到 1 亿时,系统能不能通过增加机器来扛住压力?
    • 垂直扩展 (Vertical Scaling):给原来的电脑换更强的 CPU、更大的内存(有上限)
    • 水平扩展 (Horizontal Scaling):多几台普通的电脑一起工作(理论上没有上限,这是系统设计的核心)
  • 持久
    • 存进去的数据不会丢:多副本
  • 可靠性
    • 系统是否不出错
  • 幂等性
    • 在分布式环境下,由于重试机制(Retry),同一个请求可能会发送多次。如何保证“支付一次”的请求即便发了三次,用户也只被扣一次钱?
  • 吞吐
    • QPS/TPS,并发数

Trade-offs: CAP

可用性(Availability)和一致性(Consistency)不能同时满足
前提:分区容错性(Partition Tolerance,即网络断开后系统还能继续运行)是必选项

为什么?
假设一个简单系统,只有两台服务器 Node A 和 Node B,它们各自存有一份同样的数据库副本。现在:

  • 网络断开了,Node A 和 Node B 之间无法通信(发生了 Partition)。
  • 写操作:用户向 Node A 发送请求,把自己的余额从 100 改成了 50。
  • 由于网络断开,Node A 无法告诉 Node B 余额变了。
  • 读操作:此时另一个用户访问 Node B,问余额是多少。

现在,系统只有两个选择:

选择一:保证一致性 (CP)
如果想保证一致性 (C),那么 Node B 不能返回那个旧的 100。

  • Node B 发现自己没法和 Node A 同步,于是它决定直接报错,或者告诉用户“系统维护中”。
  • 结果:数据是对的(没有返回错误数据),但系统不可用 (A) 了。

选择二:保证可用性 (AP)
如果想保证可用性 (A),那么无论如何都要给用户一个响应。

  • Node B 直接返回了它手里现有的数据 100。
  • 结果:系统一直在运行(可用),但数据是错的(Node A 是 50,Node B 是 100),不一致 (C) 了。

除此之外,比较常见的 trade-offs 还有:

  • 延迟和吞吐
  • 延迟和一致性
  • SQL 和 NoSQL
  • ACID 和 BASE
  • 有状态和无状态
  • 读优化和写优化
  • Push 和 Pull
  • ……

要根据具体的场景来决定讨论哪些 trade-offs。

核心概念

  • 计算机网络
    • HTTP
    • WebSocket
    • 负载均衡
    • CDN
  • API 设计
    • REST
    • gRPC
  • 数据建模
    • 关系型数据库
    • NoSQL
  • 数据库索引
    • B 树
  • 缓存
    • Redis
    • 缓存失效
    • 缓存崩溃
  • 分片
    • shard key
  • 一致性哈希
  • 需要知道的一些数字,用于估算性能

常见技术

系统设计就是把技术模块组合起来解决问题,因此需要知道有哪些常用的技术。对每种技术(e.g., 消息队列)应该都至少掌握一种具体的方案(e.g., Kafka)。

  • 负载均衡:Nginx
    • 把流量平均分配给多台服务器
  • API 网关:Spring Cloud Gateway
    • 鉴定权限、限流、路由
  • CDN:Cloudflare
    • 把静态资源缓存在距离用户较近的服务器上
  • 消息队列:Kafka, RabbitMQ
    • 异步处理,应对突发流量、分配系统负载
  • 分布式缓存:Redis
    • 把高频访问的数据存入内存,降低读取延迟
  • 数据库
    • 关系型数据库:MySQL, Postgres
    • NoSQL 数据库:DynamoDB, MongoDB
  • Blob 对象存储:AWS S3
  • 搜索优化数据库:Elasticsearch

架构演进的逻辑:

  1. 单机,all-in-one
  2. 拆分数据库与应用服务器
  3. 引入缓存,减轻 DB 压力
  4. 引入负载均衡与水平扩展,解决高并发
  5. 数据库读写分离/分库分表,解决数据量瓶颈
  6. 引入消息队列(异步、削峰)
  7. 微服务化,复杂业务解耦

模式

  • 写多读少,异步处理
    • 打车(轨迹上报)
    • Notification
  • 读多写少,低延迟、弱一致性
    • Feed 流
    • 电商(浏览)
  • 调度系统,强一致性
    • 支付
    • 秒杀/票务
    • 打车(实时匹配)
  • 实时交互,长连接状态保持
    • 即时通讯
    • 多人协作文档
  • 复杂数据模型与查询
    • 搜索引擎
    • 推荐系统
  • 有状态的中间件,infra 设计
    • 分布式缓存
    • 消息队列