缓存击穿(Cache Miss):
缓存击穿是指一个非常热门的或者经常被请求的缓存键在缓存中过期失效后,被大量的并发请求同时访问,导致这些请求直接击穿缓存,直接访问数据库或其他后端服务。这会导致数据库负载激增,可能引起性能问题。
解决方案:
- 使用分布式锁,确保只有一个线程可以重新生成缓存,其他线程需要等待。
- 在缓存过期前主动刷新缓存,避免同时过期的情况。
- 使用无效值(sentinel value)标记缓存正在被重新生成,其他请求检测到后等待或进行重试。
在实际开发中,通常是结合多种方案处理,比如定期生成,为了防止请求中服务等待,可以通过缓存版本号,在新的数据生成前,通过版本号获取旧的数据。
缓存雪崩(Cache Avalanche):
缓存雪崩是指缓存中的大量数据在同一时间内过期,导致大量的请求直接打到后端数据库或其他服务上。与缓存击穿不同的是,缓存雪崩是指多个缓存键同时失效,而不仅仅是一个。
解决方案:
- 设置不同的过期时间,避免缓存同时失效。
- 使用缓存预热,提前加载缓存数据,减缓缓存雪崩的影响。
- 使用多级缓存,将缓存分层,部分数据在一级缓存失效时可以从二级缓存中获取,以减轻后端负载。
- 引入缓存的自动刷新机制,避免在高负载时出现大量缓存同时失效的情况。
在实际系统设计中,通常需要综合考虑以上方案,选择适合当前场景的组合以减少缓存击穿和缓存雪崩的风险。
缓存穿透(Cache Penetration):
缓存穿透是指针对一个不存在于缓存中的键进行大量请求,导致这些请求都直接访问后端存储,从而浪费资源。
解决方案:
可以通过在缓存层增加对不存在键的判断,并设置缓存空值(如使用布隆过滤器)来缓解这个问题。
缓存膨胀(Cache Bloat):
缓存膨胀是指缓存中存储了大量不再使用的或者过期的数据,占用了过多的内存空间。
解决方案:
可以通过合理设置缓存过期时间、使用LRU等淘汰策略,以及定期清理过期数据来避免缓存膨胀。在实际的业务开发中,推荐缓存中的数据都是从数据库中读取的有时效的数据,这样缓存故障导致数据失效的时候,可以从数据库中重新读取数据,而且缓存中的数据大部分都是热点数据,可以有效的节省存储空间。