3. 缓存策略入门:本地缓存与分布式缓存对比
缓存是提升数据库读取性能、降低后端负载的核心手段。根据数据存储位置与共享范围,缓存分为本地缓存(进程内缓存)与分布式缓存(独立缓存服务)。本节从架构、性能、一致性、适用场景四个维度进行系统性对比。
3.1 本地缓存:Guava Cache 与 Caffeine
本地缓存运行在应用进程内,数据直接存储在 JVM 堆内存中,具有零网络开销、极低延迟的特点。Java 生态中最常用的实现是 Guava Cache 和 Caffeine。
| 特性 | Guava Cache | Caffeine |
|---|---|---|
| 首次发布 | 2012 | 2018 |
| 淘汰算法 | LRU(最近最少使用) | W-TinyLFU(窗口化最小频率使用) |
| 并发性能 | 分段锁 | 无锁读 + 细粒度写锁 |
| 命中率 | 基准 | 高并发下命中率提升 15%–25% |
| 内存开销 | 较高(额外对象头) | 更低(引用链优化) |
| 异步加载 | 不支持 | 支持 AsyncLoadingCache |
| 推荐场景 | 低并发、简单缓存 | 高并发、低延迟、生产级 |
生产建议:新项目优先选择 Caffeine。其 W-TinyLFU 算法能有效抵抗“突发热点”导致的缓存污染,在秒杀、Feed 流等场景下命中率显著优于 Guava Cache。
3.1.1 Caffeine 核心配置示例
Cache<String, UserProfile> userCache = Caffeine.newBuilder()
.maximumSize(10_000) // 最大条目数
.expireAfterWrite(5, TimeUnit.MINUTES) // 写入后过期
.expireAfterAccess(1, TimeUnit.MINUTES)// 访问后过期
.recordStats() // 开启命中率统计
.build();
// 手动加载
UserProfile profile = userCache.get("user:1001", key -> {
return userDao.findById(1001); // 缓存未命中时回调
});
避坑:本地缓存无法跨进程共享。当应用部署多实例时,每个节点持有独立副本,可能出现数据不一致。务必为每个缓存键设计合理的 TTL,避免“僵尸数据”长期驻留。
3.2 分布式缓存:Redis 与 Memcached
分布式缓存作为独立中间件部署,所有应用节点共享同一缓存池,天然解决数据一致性问题。Redis 和 Memcached 是两大主流方案。
| 对比维度 | Redis | Memcached |
|---|---|---|
| 数据结构 | String、Hash、List、Set、ZSet、Stream 等 | 仅 Key-Value(String) |
| 持久化 | RDB / AOF 支持 | 不支持(纯内存) |
| 高可用 | 主从 + Sentinel / Cluster | 客户端分片,无原生高可用 |
| 内存淘汰 | 8 种策略(LRU、LFU、TTL 等) | LRU 为主 |
| 网络模型 | 单线程 Reactor(6.0+ 支持多线程 I/O) | 多线程(每个核一个线程) |
| 典型延迟 | 0.1–1ms(内网) | 0.1–0.5ms(内网) |
| 适用场景 | 复杂数据结构、排行榜、分布式锁、消息队列 | 简单 KV 缓存、Session 共享 |
选型原则:如果只需要“存/取”字符串且对持久化无要求,Memcached 在纯读场景下延迟略低;一旦涉及计数器、排行榜、分布式锁或需要数据恢复,Redis 是唯一选择。
3.3 本地缓存 vs 分布式缓存:架构对比图
下图展示了两种缓存模式在微服务架构中的部署位置与数据流向。
3.4 多级缓存策略:本地 + 分布式组合
生产环境中,单一缓存模式往往无法兼顾性能与一致性。推荐采用多级缓存架构:本地缓存扛热点,分布式缓存做共享与兜底。
3.4.1 多级缓存读取流程
- L1 本地缓存:优先查询 Caffeine,命中则直接返回(延迟 < 0.1ms)。
- L2 分布式缓存:本地未命中,查询 Redis,命中后回填本地缓存。
- L3 数据库:Redis 也未命中,查询 MySQL,回填 Redis 与本地缓存。
性能收益:在典型读多写少场景下,多级缓存可将 90% 以上的请求拦截在 L1 层,数据库 QPS 降低 80%–95%。但需注意本地缓存 TTL 不宜过长(建议 1–5 秒),避免数据长期不一致。
3.5 缓存选型决策矩阵
| 决策条件 | 推荐方案 | 理由 |
|---|---|---|
| 单机部署、低并发 | Guava Cache | 简单够用,无额外依赖 |
| 单机部署、高并发 | Caffeine | W-TinyLFU 算法抗热点,命中率高 |
| 多实例、数据一致性要求高 | Redis | 共享缓存池,天然一致 |
| 多实例、纯 KV 且可接受最终一致 | Memcached | 多线程模型,简单场景延迟更低 |
| 高并发 + 数据一致性折中 | Caffeine + Redis 多级缓存 | 本地扛热点,Redis 做兜底与同步 |
关键提醒:任何缓存方案都无法替代数据库的 ACID 特性。缓存是性能加速器,不是数据保险箱。写入操作必须保证数据库为先(Cache-Aside 模式),避免缓存与数据库双写不一致。