2. 缓存基础回顾:本地缓存与分布式缓存、缓存穿透/击穿/雪崩、缓存更新策略(TTL、LRU、LFU)
在构建高性能的《Development环境缓存一致性闭环聚合查询》体系之前,必须重新夯实缓存的核心基础。本章将系统梳理本地缓存与分布式缓存的架构差异、三大经典缓存故障(穿透/击穿/雪崩)的成因与解决方案,以及 TTL、LRU、LFU 三种主流淘汰策略的适用场景。
2.1 本地缓存 vs 分布式缓存:架构与选型
缓存按部署位置与数据共享范围,可分为本地缓存(进程内缓存)与分布式缓存(跨进程共享缓存)。两者在延迟、容量、一致性模型上存在本质差异。
| 对比维度 | 本地缓存(如 Caffeine、Guava Cache) | 分布式缓存(如 Redis、Memcached) |
|---|---|---|
| 数据存储位置 | 应用进程堆内存 | 独立缓存服务节点(网络访问) |
| 访问延迟 | 纳秒级(无网络开销) | 微秒~毫秒级(依赖网络 RTT) |
| 容量上限 | 受限于单机堆内存(通常 GB 级) | 可横向扩展至 TB 级 |
| 数据一致性 | 仅单进程内一致,多实例间需额外同步 | 通过主从/集群协议保证最终一致性 |
| 典型场景 | 热点元数据、配置信息、不变字典 | 用户会话、商品详情、高并发读写 |
选型建议:在聚合查询优化中,通常采用多级缓存架构——本地缓存兜底高频只读热点,分布式缓存承载跨服务共享数据,两者配合实现延迟与一致性的平衡。
2.2 缓存穿透、击穿与雪崩
这三个故障是缓存系统最常见的稳定性杀手,理解其触发条件与防护手段是架构师的必修课。
2.2.1 缓存穿透
定义:查询一个根本不存在的数据,缓存和数据库都查不到,每次请求都穿透到数据库。
- 危害:恶意攻击或大量无效 key 直接打垮数据库。
- 解决方案:
- 缓存空对象(null 值也缓存,TTL 设置较短如 60s)。
- 布隆过滤器(Bloom Filter)前置拦截,判断 key 是否存在。
2.2.2 缓存击穿
定义:一个热点 key 在缓存失效的瞬间,大量并发请求同时穿透到数据库。
- 危害:单点热点导致数据库瞬时压力飙升。
- 解决方案:
- 互斥锁(Mutex Key):只允许一个线程去加载数据,其他等待。
- 逻辑过期(不设置 TTL,后台异步刷新)。
2.2.3 缓存雪崩
定义:大量缓存 key 在同一时间失效,或缓存节点整体宕机,所有请求直接打到数据库。
- 危害:数据库被瞬间击垮,引发级联故障。
- 解决方案:
- TTL 添加随机偏移(如基础 TTL + 随机 1~5 分钟)。
- 缓存集群高可用(Redis Sentinel / Cluster)。
- 本地缓存兜底 + 限流降级。
实践警示:在 Development 环境中,缓存穿透和击穿常因测试数据不完整而被忽略,但上线后可能瞬间暴露。建议在开发阶段就集成布隆过滤器与互斥锁逻辑,避免后期重构。
2.3 缓存更新策略:TTL、LRU、LFU
缓存系统无法无限存储,必须通过淘汰策略管理内存。TTL(Time To Live)是过期策略,LRU(Least Recently Used)和 LFU(Least Frequently Used)是淘汰策略,三者协同工作。
2.3.1 TTL(生存时间)
- 机制:为每个缓存 key 设置一个过期时间,到期后自动删除。
- 适用场景:数据有明确时效性(如验证码 5 分钟、会话 30 分钟)。
- 注意事项:避免大量 key 同时过期导致雪崩,应引入随机偏移。
2.3.2 LRU(最近最少使用)
- 机制:淘汰最长时间未被访问的数据。维护一个访问顺序链表,每次访问将节点移到头部,淘汰时移除尾部。
- 适用场景:数据访问具有时间局部性,近期访问过的数据很可能再次被访问。
- 实现方式:LinkedHashMap(Java)、Redis 的近似 LRU(allkeys-lru / volatile-lru)。
2.3.3 LFU(最不经常使用)
- 机制:淘汰访问频率最低的数据。维护每个 key 的访问计数,淘汰时选择计数最小的。
- 适用场景:数据访问具有频率局部性,高频热点数据需要长期保留。
- 注意事项:需解决“旧热点”问题(早期高频但后续不再访问的数据可能长期占据缓存)。
| 策略 | 淘汰依据 | 核心数据结构 | 典型实现 | 适用场景 |
|---|---|---|---|---|
| TTL | 时间到期 | 定时器 / 惰性删除 | Redis EXPIRE | 有时效性的数据 |
| LRU | 最近访问时间 | 双向链表 + 哈希表 | Redis allkeys-lru | 时间局部性强的负载 |
| LFU | 访问频率 | 最小堆 / 多级链表 | Redis allkeys-lfu | 频率局部性强的热点 |
实践建议:在聚合查询优化中,建议组合使用 TTL + LRU:TTL 保证数据最终一致性,LRU 保证热数据不被冷数据挤出。对于明确的热点 key(如商品详情),可考虑 LFU 策略防止被突发冷流量冲掉。
2.4 缓存更新策略选择矩阵
在实际开发中,需要根据数据特征选择最合适的策略组合。以下矩阵帮助快速决策:
| 数据特征 | 推荐策略 | 原因 |
|---|---|---|
| 强时效性(如验证码、限时活动) | TTL 为主 | 到期自动失效,保证数据新鲜度 |
| 热点集中(如热搜、排行榜) | LRU + TTL | 保留近期热点,避免冷数据污染 |
| 长尾高频(如基础配置、字典) | LFU + 无 TTL | 保留高频访问项,减少重复加载 |
| 混合负载(如聚合查询结果) | LRU + 短 TTL + 随机偏移 | 平衡热点保留与数据一致性 |