Redis作为一个高性能的内存中key-value数据结构存储系统,在我们日常开发中广泛应用于缓存、计数器、消息队列、排行榜等场景,尤其是作为作为最常用的缓存方式,它在提高数据查询效率和保护数据库方面发挥了不可磨灭的作用。但是在实际应用中,可能会出现一些Redis缓存异常。本文主要讨论Redis缓存异常及其解决方法。总结。一、背景Redis是一个完全开源的、遵循BSD协议的高性能key-value数据结构存储系统。支持数据持久化,可以将内存中的数据保存到磁盘中,不仅支持简单的Key-value类型数据还提供了list、set、zset、hash等数据结构的存储,非常强大。Redis还支持数据备份,即主从模式下的数据备份,从而提??高可用性。当然最重要的还是读写速度快,作为我们日常开发中最常用的缓存方案被广泛使用。但是在实际应用过程中,会出现缓存雪崩、缓存击穿、缓存穿透等异常情况。如果忽视这些情况,可能会带来灾难性的后果。下面主要分析这些缓存异常以及常见的处理方案并进行总结。2、缓存雪崩(1)什么是redis缓存一段时间内本应处理的大量请求,全部发送到数据库处理,导致数据库压力迅速增加,严重时甚至可能导致数据库崩溃,导致整个系统崩溃,就像雪崩一样,引发连锁效应,因此称为缓存雪崩。(2)出现上述情况的常见原因主要有以下两点:大量缓存数据同时过期,导致本应请求到缓存的数据又从数据库中获取。Redis自身出现故障,无法处理请求,自然会再次向数据库请求。(3)如何处理大量缓存数据同时过期的情况:实际设置过期时间时,应尽量避免出现大量key同时过期的场景。这避免了同时过期。添加互斥锁,这样构建缓存的操作就不会同时进行。双键策略,主键为原始缓存,备份键为副本缓存。当主键失效时,可以访问备份键。主键缓存的过期时间设置为short-term,backupkey设置为long-term。后台更新缓存策略,通过定时任务或消息队列的方式更新或移除redis缓存。对于redis本身的故障:在预防层面,可以通过主从节点搭建高可用集群,即主Redis实例挂掉后,其他从库可以快速切换到主库继续运行提供服务。如果已经发生了一些事情,为了防止数据库被大量请求压垮,可以使用服务熔断或者请求限流的方法。当然,服务熔断是比较粗糙的。停止服务,直到redis服务恢复,请求限流比较平缓,保证部分请求可以处理。3.缓存击穿(1)什么是缓存击穿?通常,在高并发系统中,大量并发用户同时请求不在缓存中而在数据库中的数据。去数据库取数据,导致数据库压力瞬间增大。与缓存雪崩不同,缓存击穿是指同时检查同一条数据。缓存雪崩就是不同的数据都过期了,很多数据找不到了,就去数据库找。(2)出现这种情况的原因通常是某个热点数据缓存过期了。由于是热点数据,并发请求量大,所以过期后,仍然会有大量请求同时到来,在缓存更新之前全部发送完。数据库在那边。(3)Whattodo这种情况常见的解决方法有两种:简单粗暴的不给热点数据设置过期时间,这样就不会过期,自然不会出现上面的情况。如果以后要清理,可以使用后台清理。加一个mutex,即过期后,除了第一个请求的查询请求,可以获取到数据库的锁请求并再次更新到缓存,其他的都会阻塞,直到锁被释放。同时,新的缓存也更新了,后续的请求都会向缓存请求,这样就不会出现缓存崩溃的情况。4、缓存穿透(1)什么是缓存穿透?意思是数据既不在redis中,也不在数据库中,这样每次请求进来,在缓存中找不到对应的key后,返回到数据库中再次查询,发现数据库是不存在,相当于两个无用的查询。这样请求就可以绕过缓存,直接去查数据库。如果这时候有人想对系统进行恶意攻击,可以故意使用空值或者其他不存在的值来频繁请求,这样会给数据库造成很大的压力。(2)出现这种现象的原因其实很容易理解。如果用户在业务逻辑中没有对某些信息进行相应的操作或处理,那么对应的存储该信息的数据库或缓存自然也就没有相应的数据。也容易出现上述问题。(3)做什么?对于缓存穿透,一般有以下三种解决方案:限制非法请求,主要指参数校验、鉴权校验等,让大量的非法请求从一开始就被阻断。它是实际业务发展中的必要手段。缓存空值或默认值。如果缓存取不到的数据没有从数据库中取回,那我们还是缓存空结果,并设置一个较短的过期时间。该设置的默认值保存在缓存中,这样会在缓存中第二次获取该值,无需继续访问数据库,可以防止大量恶意请求重复使用同一个key来获取攻击。使用布隆过滤器快速判断数据是否存在。那么布隆过滤器是什么?简单来说,可以引入多个独立的哈希函数,保证在给定的空间和误判率下,元素的权重能够被判断。因为我们知道存在这种哈希碰撞的情况,如果只使用一个哈希函数,碰撞的概率会明显增加。为了减少这种冲突,我们可以多引入几个hash函数,而Bloomfilter算法的核心思想就是使用多个不同的hash函数来解决这样的冲突。其优点是空间效率高,查询时间短,远超其他算法,缺点是会存在一定的误识别率,不能完全保证请求的key。通过了Bloomfilter的验证之后,就必须有了这个数据,毕竟理论上还是会存在冲突的,不管概率有多小。但是,只要key没有通过Bloomfilter的验证,那么key一定不存在。只要利用这一点,就可以过滤掉大部分对不存在的key的请求,正常场景下就够用了。5.其他除了以上三种常见的Redis缓存异常问题外,还有两个经常听到的名词:缓存预热和缓存降级。与其说是异常问题,不如说是两种优化方法。(1)缓存预热缓存预热是指在系统上线前后,不依赖于用户,将相关的缓存数据直接加载到缓存系统中。这样就可以避免用户请求时先查询数据库再缓存数据的问题。用户直接查询提前预热好的缓存数据,可以避免系统上线初期访问数据库的高并发流量,对数据库造成流量压力。根据数据量级的不同,有以下几种方式:数据量不大:项目启动时自动加载。数据量大:后台定时刷新缓存。数据量巨大:只对??热点数据进行预加载和缓存操作。(2)缓存降级缓存降级是指当缓存失效或者缓存服务出现问题时,为了防止缓存服务失效,导致数据库出现雪崩问题,导致数据库无法访问,但是对于一些原因,服务还是有保障的还是基本可以用的,虽然服务肯定是丢了。因此,对于不重要的缓存数据,我们可以采用服务降级策略。一般有两种方式:直接访问内存部分的数据缓存。直接返回系统设置的默认值。6.小结本文主要总结了常见的Redis缓存异常及其解决方法,总结如下图:
