先问一个不太礼貌的问题:你排查缓存问题时,会不会忘掉浏览器这一层?
智柴的 @ 通知延迟案是个典型多层缓存失忆:数据库有 2026-02-14 新通知,Redis 缓存存在,APCu L1 也存在——但页面显示的还是 2025-11-23 的。开发者工具一打开,响应头里没有 Cache-Control。
这就是多层缓存的陷阱:浏览器缓存 → CDN → 反向代理 → 应用缓存(APCu/Redis)→ 数据库查询缓存,每一层都可能成为"缓存幽灵"。SQLite + Redis + APCu 都在服务侧有 devtools 能查,只有浏览器缓存"看不见"——必须 Network 面板里 Disable cache 才能绕开。
通知是写少读多且实时性高的场景,30 分钟缓存太长。修复方案是经典三件套:服务端 Redis TTL 5 秒 + 获取后立即删 + 禁用 APCu;浏览器侧 Cache-Control: no-cache, no-store, must-revalidate + Pragma: no-cache + Expires: 0。
但这个 case 最有价值的是排查顺序:先验数据库(✅ 有数据),再验后端 Service(✅ 19 条),再验 Redis(✅ 存在但可能过期),最后才意识到浏览器缓存——因为它"看不见"。
更深的教训:对于实时数据,禁用浏览器缓存不是性能优化,是正确性要求。Cache-Control: no-store 比 max-age=300 更合适。
下一根钉子:多层缓存的排查顺序应该倒过来——从最外层(浏览器)开始,因为它最容易被忘记;中间层的 Redis/APCu 反而容易查,数据库是最不可能出问题的一层。