- 书名:《可伸缩架构》
- 作者:陈斌
- 出版社:机械工业出版社
- 副标题:互联网高并发系统的设计与实现
- 关键词:水平扩展、垂直扩展、读写分离、分库分表、缓存策略、异步处理、容量规划、负载均衡
互联网业务的核心特征之一是流量的不可预测性——从零到千万用户的爆发式增长可能发生在极短时间内。一个无法弹性伸缩的系统,在流量洪峰面前要么崩溃,要么崩溃。可伸缩架构能力的强弱,直接决定了业务的上限和企业的抗风险能力。
这三者常被混为一谈,但存在本质区别:
| 维度 |
关注点 |
典型手段 |
| 高性能 |
单个请求响应快 |
缓存、索引、CDN、异步化 |
| 高可用 |
系统持续可用 |
冗余、故障转移、多活 |
| 可伸缩 |
能承载更多流量 |
水平扩展、分片、无状态设计 |
可伸缩是前三者之间的桥梁——没有伸缩性,高性能和高可用都无法持续。
- Scale Up(垂直扩展):升级单机硬件(CPU、内存、磁盘)。物理瓶颈明显,成本非线性增长。
- Scale Out(水平扩展):增加机器数量。理论上无限扩展,但引入分布式一致性、数据分片和运维复杂度。
互联网系统的主流方向是 "Scale Out first, Scale Up when must"——优先水平扩展,仅在必要时垂直升级。
有状态服务:请求必须落在同一台机器上才能正确处理(如 Session 绑定到单机内存)。
无状态服务:任何请求可被任意节点处理,节点间无依赖。
核心原则:业务逻辑层保持无状态,状态下沉到中间件层(如 Redis、数据库)。
❌ 传统做法:Web 服务器本地 Session,通过 Sticky Session 或 Session 复制保证一致性。
✅ 推荐做法:
- Session 数据存入 Redis/Memcached,应用层只存 Session ID
- 使用 JWT 等 token 机制,状态自包含在客户端
- 接入层用一致性哈希路由,优先本地缓存,miss 后查共享存储
- 配置文件从代码中剥离,推送到配置中心(如 Nacos、Etcd、Consul)
- 启动时拉取、运行时热更新,避免文件分发
- 环境无关:同一份代码包可在开发、测试、生产环境无缝运行
- 弹性扩缩:随时加减节点,无需 session 迁移
- 故障隔离:单节点故障不影响整体
- 灰度发布:部分节点更新,流量逐步切换
- 原理:DNS 轮询,同一个域名解析到多个 IP
- 优点:天然免费,全局可用
- 缺点:无法感知后端健康状态,DNS 缓存更新慢
- 适用:多数据中心入口流量分发
- 原理:传输层(IP+端口),转发 TCP/UDP 包
- 优点:性能极高,协议无关
- 缺点:无法基于 HTTP 头部做高级路由
- 适用:流量入口,TLS 终结前的转发
- 原理:应用层,可解析 HTTP 头部、Cookie、URI
- 优点:路由策略丰富(URL 级、Header 级、Cookie 级)
- 缺点:性能低于四层
- 适用:微服务网关、API 路由、灰度策略
| 算法 |
特点 |
缺点 |
适用场景 |
| 轮询 |
均匀分发,实现简单 |
不考虑节点负载差异 |
同规格节点集群 |
| 加权轮询 |
按权重分配 |
权重配置需手动调整 |
异构集群 |
| 最少连接 |
动态感知连接数 |
状态收集有延迟 |
长连接场景 |
| 一致性哈希 |
请求/用户固定路由到节点 |
节点增减只影响部分 key |
缓存、Session 亲和 |
| 随机 |
简单、均匀 |
节点数少时不均匀 |
大数据量场景下趋于均匀 |
负载均衡器必须配置健康检查,自动剔除故障节点:
- 被动检查:连续 N 次请求失败,标记为不健康(如 Nginx proxy_next_upstream)
- 主动检查:定期发送探活请求,根据响应码/内容判定健康状态(如 Nginx health_check)
- 慢启动:新加入节点逐步增加流量,避免缓存冷启动导致雪崩
"金字塔原则"——越靠近用户的数据,应放在越快(也越贵)的存储中:
CDN(毫秒级)
↓
本地缓存(内存,微秒级)
↓
分布式缓存(Redis/Memcached,毫秒级)
↓
本地磁盘缓存(SSD,10ms级)
↓
数据库(数十毫秒级)
- 静态资源(图片、CSS、JS)全量 CDN
- 动态内容可以通过 ESI(Edge Side Includes)部分缓存
- 设置合理的 TTL 和版本号策略,避免缓存一致性问题
- 使用 Guava Cache、Caffeine、Ehcache
- 适合读多写少、数据量小、一致性要求不高的场景
- TTL 设置不宜过长(秒级到分钟级)
- 问题:各节点数据不一致,需额外机制保证
- 热点数据、Session、计数器、分布式锁
- 缓存穿透:查询不存在的数据绕过缓存直击 DB → 布隆过滤器 + 空值缓存
- 缓存雪崩:大量缓存同时过期 → 过期时间加随机偏移
- 缓存击穿:单个热点 key 过期后高并发请求 → 互斥锁 + 提前续期
推荐:Cache Aside Pattern
1. 读:先读 Cache → miss → 读 DB → 写 Cache
2. 写:先写 DB → 删除 Cache(而不是更新 Cache)
为什么不更新 Cache?
- 并发写场景下,旧值可能覆盖新值
- 延迟删除策略(Cache-Aside + Write-Behind)可降低 DB 压力
- 估算热点数据总量,预留 30–50% 缓冲区
- 大 key 拆分(>10KB 的 value 考虑压缩或拆分)
- 监控缓存命中率:低于 85% 需排查,低于 70% 视为异常
架构:主库处理写操作,从库处理读操作,通过主从复制同步。
实施要点:
- 写操作强制走主库,读操作根据场景选择
- 读写分离网关:对应用层透明(如 MySQL Router、ShardingSphere)
- 主从延迟问题:对一致性敏感的读操作,可设置"读主策略"或等待延迟窗口
- 从库负载:简单的轮询或更复杂的最小连接数策略
按业务域拆分到不同数据库:
- 用户库、订单库、商品库
- 每个库独立部署,减少单库连接数
- 问题:跨库事务困难,需分布式事务方案
按某个维度(如用户 ID、订单 ID)将数据分布到不同库/表:
分片键的选择——这是最关键的设计决策:
| 分片键 |
优点 |
缺点 |
| 用户 ID |
天然均匀,用户相关的操作集中 |
热点用户问题,跨用户查询跨分片 |
| 时间 |
按时间分片直观 |
热点集中在最新时间,历史数据空洞 |
| 哈希 |
数据分布最均匀 |
范围查询困难,扩容需重新分布 |
分片策略:
| 策略 |
说明 |
优缺点 |
| 范围分片 |
按 ID 范围划分 |
查询友好,但有热点和空洞问题 |
| 哈希分片 |
取模或一致性哈希 |
分布均匀,但范围查询跨分片 |
| 一致性哈希 |
哈希环映射 |
扩容影响小,但数据分布不一定均匀 |
| 按地理分片 |
就近存储 |
区域性,跨区域查询复杂 |
- 跨分片查询:JOIN、聚合、排序需在应用层或中间件层完成
- 分布式事务:X/Open XA 方案性能差,推荐 TCC、Saga、最终一致性 + 补偿
- 全局唯一 ID:雪花算法(Snowflake)最常见,也可用发号器服务
- 扩容难题:2N 扩容(成倍扩容降低迁移成本),或一致性哈希减少影响
- 数据迁移:不停机迁移方案(双写 + 校验 + 切换)
关系型数据库不是万能药,在以下场景考虑 NoSQL:
- KV 存储(Redis):缓存、Session、计数器
- 文档型(MongoDB):动态 Schema,JSON 文档
- 列族型(HBase、Cassandra):时序数据、大宽表、写密集型
- 搜索型(Elasticsearch):全文检索、日志分析
混合架构:MySQL 做主存储 + Elasticsearch 做搜索 + Redis 做缓存 + ClickHouse 做分析,各取所长。
同步调用的问题:
- 耦合性高:调用方必须等待被调用方
- 脆弱性:下游故障直接影响上游
- 性能受限:整体吞吐受最慢链路的制约
异步解耦的好处:
- 削峰填谷:瞬时高并发由 MQ 消化,下游按能力消费
- 流量控制:生产者速度快于消费者时,MQ 自动背压
- 故障隔离:下游宕机不影响上游继续生产
- 最终一致性:可靠投递 + 重试 + 幂等性
| 参数 |
RabbitMQ |
Kafka |
RocketMQ |
Pulsar |
| 吞吐量 |
万级/秒 |
百万级/秒 |
十万级/秒 |
百万级/秒 |
| 延迟 |
微秒级 |
毫秒级 |
毫秒级 |
毫秒级 |
| 消息可靠性 |
高(确认机制) |
高(副本机制) |
高(同步刷盘) |
高(BookKeeper) |
| 顺序消息 |
单队列支持 |
分区内有序 |
强顺序 |
分区内有序 |
| 运维复杂度 |
低 |
中 |
中 |
高 |
- 幂等消费:消费者必须能处理重复消息(用去重表或业务 ID 幂等)
- 死信队列:重试多次失败的消息进入死信,人工或自动补偿处理
- 消息不丢失:生产者确认 + 消费者 ACK + 持久化存储
- 延迟消息:使用 RabbitMQ 死信交换机或 RocketMQ 延迟级别实现定时任务
- 顺序消费:确保同一业务 ID 的消息进入同一分区,且消费者单线程处理
- 业务预测:根据历史数据和业务目标预估未来流量
- 压测摸底:单机能承载多少 QPS?
- 资源计算:根据单机容量 ×(1 + 冗余比例)计算所需节点数
- 制定扩容计划:正常扩容阈值、紧急扩容阈值
- 持续监控:实际流量 vs 预测 vs 容量,持续校准
| 压测类型 |
目标 |
工具 |
| 单机压测 |
摸清单节点上限 |
ab、wrk、hey |
| 全链路压测 |
端到端性能验证 |
JMeter、Locust |
| 容量测试 |
找到拐点(吞吐不再线性增长的点) |
Gatling、k6 |
| 稳定性测试 |
长时间加压发现内存泄漏、GC 问题 |
JMeter + Profiling |
| 异常测试 |
测试降级、熔断、限流 |
Chaos Engineering |
- 基于指标触发的自动扩缩:CPU > 70% + 持续5分钟 → 自动扩容
- HPA(Horizontal Pod Autoscaler,K8s):Kubernetes 原生,根据 CPU/Memory/自定义指标扩缩
- 预热保护:新节点启动后缓慢增加流量(防止缓存穿透和连接池打满)
- 缩容策略:流量下降后保持 N 分钟再缩容,防止频繁抖动
┌─────────────────────────────┐
│ ① 限流(流量入口) │ → 控制请求进入速率
├─────────────────────────────┤
│ ② 降级(非核心服务) │ → 牺牲局部保全局
├─────────────────────────────┤
│ ③ 熔断(下游故障) │ → 快速失败,防止级联
└─────────────────────────────┘
限流算法:
- 令牌桶:允许突发,平滑整体速率(Guava RateLimiter、Sentinel)
- 漏桶:强制平滑,不允许突发(Nginx limit_req)
- 滑动窗口:精细控制,更准确(计数器 + 时间窗口分段)
- 自适应限流:根据系统负载动态调整限流阈值(TCP Vegas 启发)
降级策略:
- 非核心功能直接返回兜底数据(如推荐位全量走缓存)
- 第三方依赖超时时间调短,避免阻塞
- 页面降级为静态版本
熔断机制:
- 错误率达到阈值(如 50%)→ 开启熔断 → 快速失败 → 恢复后半开试探
- Hystrix / Resilience4j / Sentinel 均支持熔断器模式
一个典型的互联网高并发系统架构分层(从入口到落盘):
用户层(App / Web / H5)
↓
CDN(静态资源加速)
↓
DNS / GSLB(全局负载均衡)
↓
Nginx / LVS(四/七层负载均衡)
↓
API Gateway(鉴权、限流、路由、日志)
↓
业务服务层(无状态,水平扩展)
↓
缓存层(Redis / Memcached)
↓
数据层(MySQL / NoSQL / ES)
↓ ↓ ↓ ↓
MQ DB分片 ES ClickHouse
- 单机阶段(QPS < 1000):一台应用服务器 + 单库
- 读写分离阶段(QPS 1000–10000):一主多从,读从库写主库
- 缓存层介入(QPS 1万–10万):Redis 扛热点,秒杀、排行榜
- 分库分表(QPS 10万–50万):按业务分库,按 ID 分表
- 异步解耦 + 微服务化(QPS 50万+):MQ 削峰,服务拆分
- 多活架构(QPS 100万+):异地多活、单元化
| 场景 |
推荐的伸缩策略 |
| 读多写少(内容型) |
加缓存 + 加从库 |
| 写多读少(日志型) |
队列缓冲 + 批量写入 + 分片 |
| 热点集中(秒杀) |
本地缓存 + 限流 + 异步扣减 |
| 时间序列数据 |
时间分片 + 归档 + ClickHouse |
| 全局查询需求 |
ES 做二级索引 + 客户端分片 |
- 过早分库分表:QPS 不到 5000 就急着分库分表,引入不必要复杂度
- 过度缓存:到处加缓存导致数据一致性问题比性能问题更严重
- 盲目信从指标:没有压测数据支撑的伸缩决策是拍脑袋
- 忽略运维成本:引入新组件后没有对应的自动化运维能力
- 贪多求全:一个系统塞进所有技术栈,运维灾难
陈斌的《可伸缩架构》是一本典型的国内一线工程师写的实战书。与译著相比,它的最大优势在于案例接地气——列举了大量国内互联网公司的真实场景,从微博的缓存设计到淘宝的数据库分片策略,都是有据可查的一线经验。
书的定位不是理论教材,而是一线架构师的实战手册。每一章都围绕一个核心问题展开:流量来了怎么挡、数据多了怎么存、业务复杂了怎么解耦。对于正在从"能跑就行"走向"能扛住万人"阶段的团队来说,这本书提供的经验非常有参考价值。
适合读者:有 2–5 年后端经验的工程师、正在转型架构的开发者、需要设计高并发系统的技术负责人。
阅读建议:不要当作通读书,而应作为"遇到问题时查阅的参考资料"。每次遇到性能瓶颈或伸缩性问题,先翻对应的章节,再结合实际做方案设计。
- 《大型网站技术架构:核心原理与案例分析》(李智慧):国内的经典架构书籍
- 《高可用架构》系列丛书(阿里系):更偏实战,阿里众多产品的经验沉淀
- 《Designing Data-Intensive Applications》(Martin Kleppmann):国际视野的分布式系统经典
- 《The Art of Scalability》(Martin L. Abbott):系统化的可伸缩性方法论
- 《Enterprise Integration Patterns》(Gregor Hohpe):消息集成模式的圣经
📚 读书笔记 | 架构师书架系列