《极客时间教程 - 高并发系统设计 40 问》笔记
《极客时间教程 - 高并发系统设计 40 问》笔记
基础篇
高并发系统:它的通用设计方法是什么?
三大核心手段:并发、异步、缓存
架构分层:我们为什么一定要这么做?
分层架构典型代表:
- MVC(Model-View-Controller)
- 表现层、逻辑层和数据访问层
- OSI 七层网络模型
分层的好处:
- 简化系统设计,让不同的人专注做某一层次的事情
- 可以做到很高的复用
- 更容易做横向扩展
分层架构的不足:增加了代码的复杂度
系统设计目标(一):如何提升系统性能?
核心性能指标:
- 响应时间:系统处理请求的耗时
- 吞吐量:单位时间内处理的请求数(QPS/TPS)
- 并发数:系统同时处理的请求数
性能量化:通过压测工具(JMeter、LoadRunner)测量,关注 P99/P95 等分位值
系统设计目标(二):系统怎样做到高可用?
故障转移:
- 健康检查:心跳检测
- 选举算法:
Paxos、Raft - 负载均衡:自动切换到健康节点
流量控制:
- 超时与重试:设置合理超时,避免雪崩
- 限流:控制请求速率
- 降级:非核心功能降级保核心链路
系统运维:灰度发布、故障演练、CI/CD
多活架构:同城双活、异地多活
系统设计目标(三):如何让系统易于扩展?
拆分策略:
- 优先按业务维度拆分(垂直拆分)
- 存储层水平拆分:当吞吐量达到单机瓶颈时,按分区 key 做水平扩展
数据库篇
池化技术:如何减少频繁创建数据库连接的性能损耗?
核心思想:复用已创建的对象/连接,避免频繁创建销毁的开销
典型应用:数据库连接池(HikariCP、Druid)、线程池、对象池
数据库优化方案(一):查询请求增加时,如何做主从分离?
读写分离:写入时只写主库,读数据时只读从库。通常采用一主多从架构。
读写分离的问题:主从同步的延迟
读写分离的关键:
- 主从复制
- 读写流量分发
- 代理:Cobar、Mycat
- 客户端:sharding-jdbc、TDDL
数据库优化方案(二):写入数据量增加时,如何实现分库分表?
- 垂直拆分:从业务维度,将表分为不同的库
- 水平拆分:分区 key 是关键。如 hash 取模法、范围划分
发号器:如何保证分库分表后 ID 的全局唯一性?
分布式 ID:UUID、Snowflake 算法
NoSQL:在高并发场景下,数据库和 NoSQL 如何做到互补?
LSM 树:牺牲读性能换取写入高性能。HBase、Cassandra、LevelDB 都采用此算法。
LSM 树写入流程:
- 数据写入 MemTable(内存结构,按 Key 排序)
- 通过 Write Ahead Log 备份到磁盘,防止掉电丢失
- MemTable 累积到一定规模后刷生成 SSTable(Sorted String Table)
- SSTable 达到一定数量后合并(因有序,合并速度快)
LSM 树读取流程:先查 MemTable → 未命中则查 SSTable。因数据有序,查找效率高,但因拆分成多个 SSTable,读取效率低于 B+ 树索引。
缓存篇
缓存:数据库成为瓶颈后,动态数据的查询要如何加速?
缓存分类:静态缓存、进程内缓存、分布式缓存
缓存的使用姿势(一):如何选择缓存的读写策略?
Cache Aside(旁路缓存)策略
写策略:更新表 → 删除缓存 key
读策略:
- 从缓存中读取数据
- 缓存命中 → 直接返回
- 缓存未命中 → 从数据库查询
- 查询到数据后写入缓存并返回
写策略步骤:
- 更新数据库中的记录
- 删除缓存记录
一致性问题:Cache Aside 理论上仍有较小概率导致数据不一致。写入频繁时缓存被频繁清理,影响命中率。
解决方案:
- 更新数据时更新缓存 + 分布式锁(影响写性能)
- 更新数据时更新缓存 + 较短的过期时间
Read/Write Through(读穿 / 写穿)策略

Write Back(写回)策略
核心思想:写入时只写缓存,标记缓存块为“脏”。脏块被再次使用时才将数据写入后端存储。


注意:该策略不能被应用到常用的数据库+缓存场景,是计算机体系结构中的设计(如磁盘写入)。因缓存用内存,掉电会导致脏块数据丢失(Page Cache 未刷盘)。
缓存的使用姿势(二):缓存如何做到高可用?
分布式缓存的高可用方案:
| 方案 | 说明 |
|---|---|
| 客户端方案 | 客户端配置多个缓存节点,通过算法策略实现分布式 |
| 代理层方案 | 所有请求通过代理层,代理内置高可用策略 |
| 服务端方案 | Redis Sentinel 方案 |
缓存的使用姿势(三):缓存穿透了怎么办?
缓存穿透解決方案:保存 null 值、布隆过滤器
消息队列篇
消息队列:秒杀时如何处理每秒上万次的下单请求?
核心作用:削峰、异步处理、系统解耦
消息投递:如何保证消息仅仅被消费一次?
系统架构:每秒 1 万次请求的系统要做服务化拆分吗?
拆分时机信号:
- 资源出现扩展性问题,尤其是数据库连接数瓶颈
- 大团队共同维护一套代码,研发效率和成本下降
- 系统部署成本越来越高
微服务架构:微服务化后,系统架构要如何改造?
- 服务拆分时要遵循哪些原则?
- 服务的边界如何确定?服务的粒度是怎样呢?
- 服务化之后会遇到哪些问题?如何解决?
分布式服务篇
维护篇
给系统加上眼睛:服务端监控要怎么做?
监控维度:CPU、内存、磁盘、网络
道路千万条,监控第一条,监控不到位,领导两行泪
采集方式:Agent、埋点、日志
应用性能管理:用户的使用体验应该如何监控?
APM 核心:从用户视角监控端到端体验
- 前端监控:页面加载时间、JS 错误率
- 接口监控:响应时间、成功率、错误码分布
- 链路追踪:
Zipkin、SkyWalking、Jaeger
压力测试:怎样设计全链路压力测试平台?
核心要素:
- 流量录制回放:采集真实流量作为压测脚本
- 数据隔离:压测数据与生产数据隔离(影子库/影子表)
- 全链路压测:模拟真实调用链路,覆盖所有依赖服务
配置管理:成千上万的配置项要如何管理?
配置中心核心能力:
- 配置存储分级:公共配置 + 个性配置(个性覆盖公共)
- 配置变更通知:实现配置热更新
- 性能指标:可用性优先于性能,一般要求 99.999% 甚至 99.9999%