Redis缓存穿透缓存雪崩缓存击穿的原因和解决方案.docx
Redis缓存穿透、缓存雪崩、缓存击穿的原因和解决方案 Redis缓存穿透、缓存雪崩、缓存击穿是 Redis 缓存中常见的问题,它们可能会导致数据库的负载加大,影响系统的性能。本文将详细讨论这些问题的原因和解决方案。 一、缓存穿透 缓存穿透是指查询一个根本不存在的数据,缓存层和持久层都不会命中。在日常工作中出于容错的考虑,如果从持久层查不到数据则不写入缓存层,缓存穿透将导致不存在的数据每次请求都要到持久层去查询,失去了缓存保护后端持久的意义。 造成缓存穿透的基本原因有两个。第一,业务代码或者数据出现问题(例如:set 和 get 的 key 不一致),第二,一些恶意攻击、爬虫等造成大量空命中(爬取线上商城商品数据,超大循环递增商品的 ID)。 解决方案: 1. 缓存空对象:是指在持久层没有命中的情况下,对 key 进行 set(key,null)。缓存空对象会有两个问题:第一,value 为 null 不代表不占用内存空间,空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间,可以针对这类数据设置一个较短的过期时间,让其自动剔除。第二,缓存层和存储层的数据会有一段时间窗口的不一致,可能会对业务有一定的影响。 2. 布隆过滤器拦截:在访问缓存层和存储层之前,将存在的 key 用布隆过滤器提前保存起来,做第一层拦截,当收到一个对 key 请求时先用布隆过滤器验证是否存在,然后再访问缓存层和存储层。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一个确定的误识别率和删除困难。 二、缓存雪崩 缓存雪崩是由于缓存层承载着大量请求,有效地保护了存储层,但是如果缓存层由于某些原因不可用(宕机)或者大量缓存由于超时时间相同在同一时间段失效(大批 key 失效/热点数据失效),大量请求直接到达存储层,存储层压力过大导致系统雪崩。 解决方案: 1. 高可用设计:可以把缓存层设计成高可用的,即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务。利⽤sentinel 或 cluster 实现。 2. 多级缓存:采⽤多级缓存,本地进程作为一级缓存,Redis 作为二级缓存,不同级别的缓存设置的超时时间不同,即使某级缓存过期了,也有其他级别缓存兜底。 3. 缓存标记:记录缓存数据是否过期,如果过期会触发通知另外的线程在后台去更新实际 key 的缓存。 三、缓存击穿 缓存击穿是系统中存在以下两个问题时需要引起注意:在缓存失效的瞬间,有大量线程来重建缓存,造成后端负载加大,甚至可能会让应用崩溃。 解决方案: 1. 分布式互斥锁:只允许一个线程重建缓存,其他线程等待重建缓存的线程执行完,重新从缓存获取数据即可。 2. 永不过期:当前 key 是一个热点 key(例如一个秒杀活动),并发量非常大。重建缓存不能在短时间完成,可能是一个复杂计算,例如复杂的 SQL、多次 IO、多个依赖等。 缓存穿透、缓存雪崩、缓存击穿都是 Redis 缓存中需要注意的问题,了解它们的原因和解决方案,可以帮助我们更好地使用 Redis 缓存,提高系统的性能和可靠性。