本地负缓存
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 前移到进程内,省一次网络往返。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
相关文章智能推荐
1
微服务之间如何传递 trace
后端开发跨服务传递的是 trace 上下文而非 tracer:HTTP header、gRPC metadata 与 MQ 消息头的标准做法。
2
一致性哈希:consistent 与 rendezvous 的对比
后端开发两种分布式哈希的均匀度与耗时对比结论:节点少选 rendezvous,节点多且时间敏感选 consistent。
3
微服务鉴权与网关职责
后端开发Gateway 负责认证、Service 负责授权:身份上下文透传、反例风险与文件服务落地场景。
4
Kafka 的分区与副本机制
后端开发Kafka Broker/Topic/分区的关系,以及 leader-follower 副本的读写与冗余备份机制。
5
MySQL 索引与慢查询优化
后端开发慢查询 200ms 阈值、JOIN 对数据量的影响、IN 列表过大丢索引与分批查询。
随机文章随机推荐











