选择旁路缓存、写穿或延迟双删时,明确一致性边界。
核心思路
缓存键包含业务版本,设置带随机抖动的过期时间防止雪崩。热点空值可短暂缓存,极热键考虑本地缓存和请求合并。
落地步骤
不要把 Redis 当成无容量上限的数据库。监控内存、淘汰、命中率和大键,设计降级路径以应对缓存不可用。
验证清单
实施后不要只确认“能运行”,还应检查错误率、延迟、资源占用和异常路径。把验证命令、预期结果和回滚方式写进变更记录,后续维护会轻松很多。
小结
好的工程实践不是堆叠工具,而是用清晰边界、可观察结果和可逆变更降低长期成本。先解决最重要的问题,再逐步自动化。
可执行实践
缓存键包含业务与 schema 版本,TTL 加随机抖动;空结果短暂缓存防穿透,热点回源使用请求合并。写路径明确允许的短暂不一致窗口。
验证与退出条件
监控命中率、内存、evicted_keys、过期和大键。演练 Redis 不可用时应用能限流或回源,禁止缓存故障直接拖垮数据库。
实践场景
以“为热点商品详情增加缓存”为例。实施前先保存当前版本、配置和关键指标基线,写明成功条件与停止条件;涉及生产数据或外部写入时,先在隔离环境验证。
分步实施
定义 key 版本、TTL 抖动、空值缓存和失效责任;读路径允许回源,写路径选择旁路或事件失效并记录延迟。每完成一步都记录可观察结果,不把命令返回零等同于业务正确。
故障演练
模拟击穿、穿透、雪崩、Redis 超时和旧事件乱序,确认数据库不会被瞬时打满。演练应使用可清理的测试数据,并验证告警、日志和恢复路径,而不只是确认系统最终又能访问。
观测与回滚
观察命中率、回源 QPS 和陈旧窗口;异常时关闭缓存读但保留数据库保护与限流。变更单中应写清负责人、观察窗口、阈值和回滚触发器,避免故障发生后再临时争论。
完成后把使用的版本、关键命令、观测窗口和结果写入变更记录。没有验证证据的“已完成”不能作为上线结论。
第二轮实践复核
可复用交付物: Key 规范、TTL 策略、回源保护和失效事件。复用时先固定软件版本、依赖锁文件、测试数据规模和运行环境;文章中的命令包含占位符,必须替换成自己的非生产目标后再执行。
最低验证: redis-cli --scan --pattern "cache:*" | head; redis-cli TTL cache:sample
执行记录要保存命令、退出码、关键输出、观察窗口和回滚结果。若验证会产生写入,先使用隔离环境或 dry-run;任何失败都不能通过扩大权限、关闭校验或跳过测试来“解决”。
完整实战:商品详情 Cache-Aside
读路径先查缓存,未命中再读数据库并写入;写路径先提交数据库,再删除缓存。删除而不是直接更新能减少多写入者的竞态,但仍存在读请求在删除后写回旧值的窗口,因此缓存只承载可容忍短暂陈旧的数据。
1 | key = product:{tenant}:{product_id}:v3 |
键包含租户和 schema 版本,TTL 加抖动避免同批键同时过期。值中保留来源版本,便于诊断陈旧数据。不能把权限判断结果按错误维度共享,也不能让缓存命中绕过当前用户鉴权。
防击穿、穿透与雪崩
| 风险 | 表现 | 处理 |
|---|---|---|
| 热点击穿 | 一个热键过期,大量请求回源 | singleflight/短锁 + 过期数据兜底 |
| 缓存穿透 | 不存在 ID 持续回源 | 输入校验、短 TTL 空值、限流 |
| 集中过期 | 数据库瞬间升载 | TTL 抖动、分批预热、容量保护 |
| Redis 故障 | 所有请求直接冲击数据库 | 回源并发上限、熔断、负载削减 |
分布式锁必须有过期和持有者 token,只允许持有者释放;即使有锁,数据库仍需承受锁服务失效。对强一致余额、权限撤销等数据,不要用普通 cache-aside 假装强一致。
验证缓存是否真的有收益
同时看命中率、按 keyspace 的 P95、回源 QPS、过期/淘汰、内存碎片、热键分布和数据库负载。高命中率也可能掩盖序列化很慢或数据长期陈旧。测试冷启动、热点键、Redis 超时、批量过期和数据库降速,确认回源有界且不会形成重试风暴。
上线先给少量租户启用,保留绕过缓存的开关。回滚时关闭读缓存并停止填充即可,不要为了“清干净”对共享 Redis 执行宽泛删除;旧版本键依靠命名空间和 TTL 自然退出。
一手资料
资料与版本边界复核日期:2026-08-22。工具行为可能演进,实施前以锁定版本对应的官方文档为准。
评论