目录
缓存雪崩
一、产生原因
二、解决方案
缓存穿透
一、产生原因
二、解决方案
缓存雪崩
Redis缓存雪崩是指在系统高并发情况下,Redis缓存中的大量数据集中失效,导致系统的连续错误请求,进而造成数据库的过载和系统的崩溃。以下是对Redis缓存雪崩的详细解释:
一、产生原因
- 缓存数据过期时间设置过于接近:当大量的缓存数据设置了相同的过期时间,或者过期时间非常接近时,这些缓存数据可能会在同一时刻失效,从而导致缓存雪崩。
- 缓存服务器故障或宕机:如果Redis缓存服务器出现故障或宕机,那么缓存层将无法正常提供服务,所有的请求都会直接到达存储层,从而引发缓存雪崩。
- 系统访问高峰期:在系统访问高峰期,大量的请求可能会同时涌入Redis缓存,如果此时缓存层无法有效处理这些请求,也可能导致缓存雪崩。
二、解决方案
- 设置合理的缓存失效时间:合理设置缓存的过期时间,让缓存的失效时间分布在一个时间轴上,避免大量的缓存在同一时间失效。可以在原有失效时间的基础上增加一个随机值,如1~5分钟的随机范围,使每个缓存过期时间的重复率降低。
- Redis数据的热备份:通过将缓存数据备份到其他Redis实例中,当某个Redis实例发生故障或宕机时,可以快速切换到备份实例,保证系统的正常运行。
- 限流和降级:通过限制系统的访问流量,防止系统瞬时的高并发访问。同时,可以通过降级策略,如提供默认数据或静态页面等,来减轻系统的负载压力,保证系统的稳定性。
- 缓存预热:在系统上线之前,可以提前将热点数据加载到缓存中,以降低对数据库的访问压力。通过缓存预热可以尽可能减少缓存失效带来的冷启动问题,减轻雪崩的影响。
- 使用分布式缓存:将缓存数据分散存储在多个Redis实例中,避免单个Redis实例的故障引发雪崩问题。通过使用一致性哈希算法等技术,将缓存数据均匀地分布到多个节点上,提高系统的容错性和稳定性。
- 高可用性设计:使用Redis哨兵模式或Redis集群部署方式,确保缓存层的高可用性。即使个别Redis节点或机房宕掉,整个缓存层仍然可以使用。
- 互斥锁控制:在高并发场景下,为了避免大量的请求同时到达存储层查询数据、重建缓存,可以使用互斥锁控制。当缓存未命中时,对key加锁,然后从存储层查询数据并写入缓存层,最后释放锁。若其他线程获取锁失败,则让线程休眠一段时间后重试。
缓存穿透
Redis缓存穿透是指用户请求的数据在缓存和数据库中都不存在,导致每次请求都会直接访问数据库,进而可能给数据库带来巨大压力的现象。以下是对Redis缓存穿透的详细解释:
一、产生原因
- 数据不存在:当客户端请求的数据在缓存中和数据库中都不存在时,这些请求会绕过缓存直接到达数据库,导致数据库压力增大。
- 恶意攻击:攻击者可能会故意请求系统中不存在的数据,利用缓存穿透来消耗数据库资源,进而达到攻击目的。
二、解决方案
-
缓存空值:
- 对于查询结果为空的操作,可以将空结果缓存起来(通常设置一个较短的过期时间)。
- 这样,当相同的请求再次到来时,可以直接从缓存中获取空结果,避免访问数据库。
- 但需要注意,如果短时间内存在大量恶意请求,这种策略可能会导致缓存系统占用大量内存。因此,可以结合风控系统对用户请求进行统计和封禁。
-
布隆过滤器:
- 布隆过滤器是一种数据结构,用于快速判断一个元素是否存在于一个集合中。
- 它通过多个哈希函数将元素映射到位数组上的多个位置,如果所有位置的值都为1,则认为元素存在;如果存在任一位置的值为0,则认为元素不存在。
- 使用布隆过滤器可以在查询数据库之前快速判断数据是否存在,从而避免不必要的数据库访问。
- 但需要注意的是,布隆过滤器存在一定的误判率,即可能会将不存在的元素误判为存在。因此,在设置布隆过滤器时需要根据实际情况调整其参数以降低误判率。
-
使用锁机制:
- 当发现缓存不存在时,可以使用锁机制来避免多个相同的请求同时访问数据库。
- 只有一个请求会获得锁并查询数据库,其他请求会等待锁释放后再访问缓存或数据库。
- 这种策略可以确保在数据库查询期间不会有其他请求重复访问数据库,从而减轻数据库压力。
- 但需要注意的是,如果锁持有时间过长或锁释放不及时,可能会导致其他请求长时间等待甚至死锁。因此,需要合理设置锁的持有时间和释放策略。
-
组合方案:
- 在实际应用中,可以结合多种策略来解决缓存穿透问题。
- 例如,可以先使用布隆过滤器进行初步筛选,如果数据不存在则直接返回失败;如果数据可能存在但缓存中不存在,则使用锁机制确保只有一个请求访问数据库;最后,将查询结果(无论是否为空)都缓存起来以供后续请求使用。