视频加载失败

本地负缓存

473 字
2 分钟
本地负缓存

把不存在/失败结果缓存在本地内存里,短时间内直接返回,避免重复访问下游系统。

id=999999 不存在 → 缓存 60 秒

后面 60 秒:

直接返回不存在,不用查 DB

为什么需要#

典型的缓存只缓存「查到了」的结果,但线上更耗资源的往往是查不到的请求:

  • 缓存穿透:不存在的 key 每次都要打到数据库,负面结果不缓存,等于每次都白查一遍。
  • 下游故障放大:某个依赖超时/报错后,上层不断重试同样的失败请求,把故障放大。
  • 恶意或爬虫流量:大量轮询不存在的资源 ID。

负缓存(negative caching)就是把「不存在 / 失败」也当成一种结果缓存起来,短时间内对同一 key 直接复用这个结论。

实现要点#

// 极简示意:本地 map + 过期时间
var negativeCache sync.Map // key -> expireAt
func GetProfile(ctx context.Context, id string) (*Profile, error) {
if exp, ok := negativeCache.Load(id); ok && time.Now().Before(exp.(time.Time)) {
return nil, ErrNotFound // 命中负缓存,直接返回
}
p, err := repo.Find(ctx, id)
if errors.Is(err, ErrNotFound) {
negativeCache.Store(id, time.Now().Add(60*time.Second))
return nil, err
}
return p, err
}
  • TTL 要短:负缓存是「暂时的结论」,实体可能随后就被创建。一般秒级到一分钟,宁短勿长。
  • 只缓存确定性失败:不存在 可以缓存;超时/网络错误 不应该固化为负缓存,否则下游恢复后仍被挡住。
  • 要有容量上限与淘汰:本地内存是无底洞风险,配合 LRU 或分片 + 定期清理,防止被不存在的 key 撑爆。
  • 命中打点:监控负缓存命中率,异常升高往往意味着上游调用方在犯错或有攻击流量。

与「缓存空对象」是同一个思路,只是把空值判断从 Redis 前移到进程内,省一次网络往返。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

本地负缓存
https://blog.81vm3.xyz/posts/local-negative-cache/
作者
Blume
发布于
2025-12-03
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Blume
I build interesting things.
公告
欢迎来到我的博客!
分类
标签
最新动态
站点统计
文章
38
分类
5
标签
98
总字数
23,078
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录