多级缓存设计:从 CPU 到分布式缓存的层层加速
什么是多级缓存
多级缓存(Multi-Level Cache)是一种分层缓存架构,将不同速度、不同容量、不同成本的存储介质组织成缓存层级。请求从最快的层级开始查询,逐级向下,直到找到数据或最终回源数据库。
典型的互联网系统采用三级缓存架构:
浏览器缓存 → CDN 缓存 → Nginx 本地缓存 → 应用本地缓存 → Redis 分布式缓存 → 数据库
为什么需要多级缓存
单一种类的缓存总有短板:
| 缓存类型 | 速度 | 容量 | 成本 | 分布式 |
|---|---|---|---|---|
| 本地内存 | 纳秒级 | GB 级 | 低 | 否 |
| Redis | 毫秒级 | 百 GB 级 | 中 | 是 |
| 数据库 | 毫秒~秒级 | 无限 | 高 | 是 |
多级缓存用空间换时间,用成本换性能。
经典三级缓存架构
第一级:本地缓存(L1)
使用 Caffeine/Guava Cache/Ehcache,存储在应用进程内,速度极快(微秒级):
@Bean
public Cache<String, Product> localCache() {
return Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(5, TimeUnit.SECONDS) // 短 TTL 保证新鲜度
.recordStats()
.build();
}
优点:无网络开销,速度最快
缺点:容量有限、重启丢失、多副本不一致
第二级:分布式缓存(L2)
Redis/Memcached,统一集群,所有应用节点共享:
public Product getProduct(Long id) {
// 先查本地缓存
Product product = localCache.getIfPresent(id);
if (product != null) return product;
// 本地未命中,查 Redis
String json = redis.opsForValue().get("product:" + id);
if (json != null) {
product = JSON.parseObject(json, Product.class);
localCache.put(id, product); // 回填本地缓存
return product;
}
// 都未命中,查数据库
product = productDao.findById(id);
redis.opsForValue().set("product:" + id, JSON.toJSONString(product), 30, TimeUnit.MINUTES);
localCache.put(id, product);
return product;
}
第三级:数据库(L3)
最终数据源,做好保护:读库、限流、连接池管理。
多级缓存的一致性问题
更新难题
数据发生变更时,需要同时更新/失效多个缓存层级:
public void updateProduct(Product product) {
productDao.update(product); // 更新数据库
redis.delete("product:" + product.getId()); // 删除 Redis 缓存
localCache.invalidate(product.getId()); // 失效本地缓存
}
本地缓存一致性方案
- 短 TTL:本地缓存 TTL 设为 5-10 秒,容忍短暂不一致
- 消息通知失效:更新时发送 MQ 消息,所有节点消费后失效本地缓存
- Redis 订阅 + 本地监听:使用 Redis Key 失效事件的订阅机制
缓存的过期联动
建议不同层级的 TTL 呈递进关系:
L1 本地缓存:3~5 秒(最快感知变化)
L2 Redis: 15~30 分钟(兜底,保护数据库)
L3 数据库: 持久化(最终数据源)
多级缓存的挑战
缓存穿透放大
如果数据不存在,每一级都要查一遍。解决方案:布隆过滤器在 L1 前拦截。
内存压力
每个应用节点都存一份本地缓存,需要精确估算内存占用。
热点数据感知
不是所有数据都适合进入本地缓存。需要识别真正的热点:
// 记录访问频率,热点自动升级到本地缓存
public Product getSmart(Long id) {
// 访问频率低,直接从 Redis 查
if (!isHotKey(id)) {
return getFromRedis(id);
}
// 热点数据走多级缓存
return getFromMultiLevel(id);
}
几种常见架构对比
| 架构 | 适用场景 | 延迟 | 复杂度 |
|---|---|---|---|
| 单 Redis | 中小系统 | ~10ms | 低 |
| 本地+Redis | 高并发读 | ~1μs+1ms | 中 |
| CDN+Nginx+Redis+DB | 大规模互联网 | 动态 | 高 |
| 数据库查询缓存 | 低并发 | ~100μs | 极低 |
面试要点
- 多级缓存的核心思想是用距离换速度,越靠近 CPU 越快但也越贵
- 能说清三级缓存的典型架构:本地缓存 → Redis → 数据库
- 一致性是最难的考点:短 TTL + 消息失效 + 驱逐监听
- 本地缓存不是所有数据都适合,只有热点数据 + 读多写少才值得
- 能提到”布隆过滤器防穿透”是高级思维
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容