缓存能提升性能,也能制造很隐蔽的数据问题。设计缓存时,不能只问“加在哪里最快”,还要问:数据能不能过期、过期后怎么重建、更新时怎么失效、故障时能不能降级。
常见缓存可以分成两类:本地缓存和集中式缓存。
本地缓存适合轻量热点数据
本地缓存直接放在应用进程内,访问最快,不需要网络开销。适合缓存这些内容:
- 配置项
- 字典表
- 小型规则
- 很少变化的热点数据
本地缓存的问题也明显:每个实例都有一份,更新不容易同步。如果数据变化频繁,或者必须强一致,本地缓存就不合适。
使用本地缓存时,至少要设置:
- 最大容量
- 过期时间
- 淘汰策略
- 刷新方式
不要让本地缓存无限增长,也不要缓存大对象。
Redis 适合跨实例共享
Redis 适合多个应用实例共享缓存。比如用户会话、热点数据、计数器、排行榜、分布式限流等。
但 Redis 不是“远程 HashMap”。使用 Redis 要关注:
- key 设计是否清晰。
- value 是否过大。
- 过期时间是否合理。
- 是否存在热点 key。
- 故障时业务怎么降级。
缓存层一旦变成所有请求的必经路径,Redis 本身就会成为核心依赖。监控、限流、超时和降级必须跟上。
缓存失效比缓存写入更重要
缓存真正难的是失效。
常见策略有:
- 设置 TTL,到期自动失效。
- 数据更新时主动删除缓存。
- 先更新数据库,再删除缓存。
- 通过消息通知各实例刷新。
如果数据一致性要求不高,TTL 是最简单稳妥的方案。如果数据更新后必须尽快可见,就要配合主动失效或消息通知。
不要把缓存更新链路设计得过于复杂。越复杂,越容易出现数据库成功、缓存失败、消息丢失、重复刷新等边界问题。
防穿透、防击穿、防雪崩
缓存常见三类风险:
缓存穿透:请求的数据根本不存在,每次都打到数据库。可以用空值缓存、参数校验或布隆过滤器处理。
缓存击穿:某个热点 key 过期,大量请求同时打到数据库。可以用互斥重建、逻辑过期或提前刷新处理。
缓存雪崩:大量 key 同时过期,数据库瞬间承压。可以给过期时间加随机抖动,避免同一时间集中失效。
这些策略不必一开始全部上,但高频接口必须提前考虑。
实用结论
缓存设计的核心不是“加一层 Redis”,而是明确数据生命周期和一致性边界。
本地缓存适合进程内轻量热点数据,Redis 适合跨实例共享状态。无论哪种缓存,都要控制容量、设置过期、设计失效、准备降级。缓存越靠近核心链路,越要把失败场景当成正常场景来设计。




