[系统设计 - 缓存设计专题] 1. 缓存分层架构
编辑
3
2026-07-12
缓存分层架构
标准分层链路:
L0 CDN 边缘缓存 → L1 网关 / 反向代理缓存 → L2 应用本地缓存(进程内) → L3 分布式共享缓存(Redis) → L4 数据库层缓存(Buffer Pool / 查询缓存)
每层统一按 4 个维度展开:
- 使用场景
- 本层能解决什么问题
- 本层固有、无法彻底根除的短板(解决不了的问题)
- 引入该层后的最终业务结果
L0. CDN 边缘缓存(最外层,用户侧)
1. 使用场景
静态资源:图片、视频、JS/CSS、静态页面、公共无敏感接口、首页骨架、静态配置文件;
全国 / 全球多地域访问、大流量公开静态内容;
不包含用户隐私、个性化数据。
2. 能解决的问题
- 跨地域网络延迟,就近节点响应,大幅降低跨城 / 跨运营商耗时;
- 削峰:海量静态请求不回源业务服务器,减轻源站带宽、CPU 压力;
- 带宽成本降低,大文件下载分流;
- 抵御 CC 攻击,边缘节点拦截无效请求。
3. 固有无法解决的问题
- 强一致性无法实现:CDN 多节点副本,统一刷新有延迟,无法做到实时同步脏数据;
- 不支持个性化、私有数据缓存:缓存基于 URL,无法按用户 ID 隔离,缓存用户隐私会泄露;
- 容量成本高、粒度粗:只适合大体积静态资源,不适合高频小粒度业务对象;
- 无法做复杂业务逻辑缓存:不支持 Hash、ZSet、计数器等数据结构;
- 节点故障、缓存穿透回源、热点 URL 打爆源站只能缓解不能根除。
4. 最终结果
静态流量 90%+ 在边缘拦截,源站 QPS 大幅下降,页面加载速度显著提升;但动态个性化接口完全无法依赖 CDN。
L1. 网关 / Nginx 反向代理缓存(机房入口层)
1. 使用场景
公共开放接口、无登录通用页面、高频只读短接口、活动页、商品列表公共数据;
统一入口拦截流量,在进入业务服务前拦截重复请求;
Lua 脚本缓存接口响应报文。
2. 能解决的问题
- 屏蔽大量重复请求,减少下游应用服务并发压力;
- 统一缓存 TTL、统一限流熔断、统一缓存失效规则;
- 减轻应用服务网络、序列化开销;
- 多实例服务共享同一层缓存,相比本地缓存集群一致性更好。
3. 固有无法解决的问题
- 无业务上下文隔离:很难精细按用户、租户、业务模块隔离缓存;
- 缓存粒度粗,只能缓存完整 HTTP 响应,无法缓存单个业务对象;
- 网关集群多节点,多副本存在短暂不一致;
- 不支持复杂数据结构,仅支持 KV 字符串缓存;
- 无法读取应用内存对象,必须序列化报文存储。
4. 最终结果
公共接口流量提前拦截,下游服务并发量下降 30%~60%;个性化、带用户身份的数据无法使用该层缓存。
L2. 应用本地缓存(进程内 LRU)
1. 使用场景
- 超高热点小数据:基础配置、字典、分类、热门商品基础信息、活动开关;
- 单实例高频重复访问、访问延迟敏感链路(P99 优化);
- 兜底防护:分布式缓存宕机降级使用;
- 低变更、读多写少、可容忍短暂不一致的数据;
- 热点 key 打散,防止 Redis 单节点热点。
2. 能解决的问题
- 零网络 RTT,纳秒级访问,消除 Redis 网络往返、序列化 / 反序列化 CPU 消耗;
- 打散热点流量:同一热点 key 分散到所有应用实例,不会集中压垮 Redis 单节点;
- 分布式缓存故障降级兜底,避免全量穿透 DB;
- 减轻 Redis 集群 QPS 压力,提升整体缓存命中率;
- 轻量、无额外中间件运维成本。
3. 固有无法解决的问题(核心短板)
- 集群数据天然不一致(最致命):每个应用实例独立内存,更新后仅单实例失效,其他实例仍存旧数据;即便用 Pub/Sub 广播失效,仍存在消息延迟、丢消息导致脏读;无法做到集群实时强一致。
- 容量受单实例内存限制:堆内存有限,只能存百 MB 级热点,无法承载全量业务数据;单服务扩容实例越多,总缓存副本越多,内存总占用线性上涨。
- 服务重启全量失效:发布、重启、扩缩容时本地缓存清空,瞬间大量请求穿透 Redis,引发缓存击穿风暴。
- 无法跨服务共享:A 服务缓存的数据,B 服务不能复用,重复缓存浪费内存。
- 无持久化,进程退出数据丢失;淘汰算法只能基于本实例访问统计,无法感知全局冷热。
4. 最终结果
最热流量直接内存命中,P99 延迟大幅优化,Redis 压力减半;但必须接受短时间数据不一致,需要分布式缓存做统一数据源兜底。
L3. 分布式共享缓存(Redis Cluster)
1. 使用场景
- 全服务集群共享业务数据:用户信息、购物车、库存、订单、商品详情;
- 需要跨实例、跨服务统一数据视图,对一致性有基础要求;
- 数据量较大,单实例内存无法承载;
- 需要分布式能力:分布式锁、计数器、排行榜、消息队列、过期淘汰;
- 本地缓存失效后统一回写的唯一可信缓存源。
2. 能解决的问题
- 全集群统一数据副本,所有应用读取同一份缓存,天然解决本地缓存集群不一致问题;
- 容量横向扩容,百 GB 级存储,可承载全量热点业务数据;
- 丰富数据结构、原子操作,支撑各类业务计数、限流、锁场景;
- 持久化 RDB/AOF,进程重启不丢失缓存数据;
- 主从 / 集群高可用,单节点故障自动切换;
- 统一缓存更新入口,所有业务写操作统一修改此处,作为缓存事实标准。
3. 固有无法解决的问题
- 存在网络开销:每次读写都有 RTT(0.5~2ms),并发极高时网络 IO、序列化成为瓶颈;
- 热点 key 问题无法根除:极端热点会集中打到单个分片主节点,造成 CPU 打满;
- 集群故障、主从切换、槽迁移会产生短暂不可用,仍有穿透 DB 风险;
- 无法消除序列化开销,对象进出 Redis 必须编解码;
- 多机房部署存在跨城同步延迟,异地多活天然不一致;
- 无法完全规避缓存穿透、击穿、雪崩三大经典问题,只能通过策略缓解。
4. 最终结果
全服务共享统一缓存数据源,解决集群数据同步问题,承载绝大多数业务读写;但延迟高于本地缓存,高并发下网络与序列化存在性能瓶颈,依赖本地缓存做前置加速。
L4:数据库层缓存(MySQL Buffer Pool / 索引缓存)
1. 使用场景
所有最终落库查询兜底;低频冷门数据、未缓存业务数据;复杂多表联查、聚合统计;无业务缓存兜底时的最后性能防线。
2. 能解决的问题
- 磁盘 IO 拦截,热点索引、行数据加载到内存,避免每次查询读磁盘;
- 无业务缓存时,兜底降低数据库磁盘压力;
- 索引页、数据页自动冷热淘汰,无需业务手动维护 TTL;
- 事务内数据一致性天然保障。
3. 固有无法解决的问题
- 延迟最高:即使命中 Buffer Pool,仍有 SQL 解析、锁、事务、内存拷贝开销,5~50ms;
- 数据库资源上限极低,大量并发查询会打满 CPU、连接池;
- 无法做复杂业务计算、分布式协同(锁、限流、计数);
- 容量有限,优先缓存索引,业务数据缓存容量不足;
- 无法拦截重复相同查询,每次都要执行 SQL 逻辑。
4. 最终结果
缓存全层全部失效后的最后兜底,大幅降低磁盘 IO;但性能最差,不能作为高并发流量的主力缓存层。
- 0
- 0
-
分享