Java 后端
Redis 缓存三大问题:把缓存做成系统防线
从设备档案高频查询出发,拆解缓存穿透、击穿、雪崩与一致性窗口的工程取舍。
核心洞察:缓存不是数据库前面的一层加速器,而是一套针对读压力、热点和故障传播的控制系统。 霓虹港首页需要展示数万台设备的摘要。绝大部分请求读取少量热点设备,Cache Aside 可以显著减少数据库压力;但一旦把“有 Redis”误认为“系统安全”,流量尖峰会迅速暴露三个不同问题。
穿透:查询根本不存在的数据
攻击或异常客户端持续查询不存在的设备编号。缓存没有命中,数据库也没有命中,每次请求都会穿过两层。解决并非只有布隆过滤器:数据规模小、变更频繁时,短 TTL 的空值缓存更简单;数据量大且键集合稳定时,布隆过滤器能在最前面拦住绝大多数无效请求。
DeviceSummary value = redis.get(key);if (value != null) return value;if (redis.hasNullMarker(key)) return null;DeviceSummary loaded = repository.findSummary(id);redis.cache(key, loaded, ttl);空值缓存必须设短过期时间,避免新设备刚创建却长期被判定不存在。
击穿:一个热点 Key 同时失效
某个重点设备页面过期时,数千并发请求同时回源。它们请求的是同一份数据,但数据库收到的是数千次相同查询。互斥重建让一个请求负责加载,其他请求短暂等待;逻辑过期则始终返回旧值,并异步刷新。前者一致性更强,后者延迟更稳定。
| 策略 | 首次过期体验 | 一致性 | 适合场景 |
| 互斥锁 | 少量请求等待 | 较强 | 更新敏感的详情 |
| 逻辑过期 | 返回旧值 | 最终一致 | 高可用读模型 |
讨论与反应