Redis缓存经常会涉及到:缓存雪崩、缓存穿透、缓存击穿等问题,下面详解常见的Redis缓存问题@mikechen
缓存雪崩
Redis缓存雪崩是指在某一个时间段,大量的缓存数据同时过期或者失效,导致缓存服务器无法承受所有请求的情况。
这种情况下,大量的请求会打到数据库上,从而导致数据库崩溃或者瘫痪,甚至会影响整个系统的稳定性和可用性。
如下图所示:
数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。
造成缓存雪崩的原因有很多,比如:
1. 缓存大面积失效。例如,缓存数据设置了相同的过期时间,导致在同一时刻失效。
2. 缓存数据不均匀分布。例如,某些数据集中在某几个键上,这些键过期后,大量的请求就会打到数据库,彼此之间会互相竞争,使得数据库负载不断增加,出现阻塞甚至崩溃的情况。
3. 数据库崩溃。当数据库崩溃后,整个系统的请求都会打到缓存服务器上,如果缓存服务器无法处理这些请求,就会出现缓存雪崩的情况。
为了避免Redis缓存雪崩,可以采取以下措施:
1. 尽量避免缓存数据同时失效
可以将缓存数据的过期时间随机设置,或者采用懒加载的方式,当缓存数据失效时再去数据库中重新加载。
2. 均匀分布缓存数据
可以将缓存数据尽量均匀地分布在不同的键上,避免某些数据集中在某几个键上,导致大量请求打到数据库上。
3. 设置自动降级和熔断机制
当缓存服务器无法承受大量请求时,可以设置自动降级和熔断机制,例如返回错误码或者暂时停止接收请求,以减少数据库的负载。
4. 加入高可用机制
可以采用Redis集群或者主从复制的方式,确保Redis缓存服务器的高可用性,避免因为单点故障而导致整个系统不可用。
缓存穿透
缓存穿透是指查询一个一不存在的数据,如下图所示:
例如:从缓存redis没有命中,需要从mysql数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。
缓存穿透解决思路:
如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库。
设置一个过期时间或者当有值的时候将缓存中的值替换掉即可。
可以给key设置一些格式规则,然后查询之前先过滤掉不符合规则的Key。
缓存击穿
Redis缓存击穿是指当某个热点key过期或者是从未被缓存过,同时又有大量并发请求访问该key时,这些请求会导致数据库过载,从而影响整个系统的稳定性和可用性。
如下图所示:
造成Redis缓存击穿的原因主要包括以下几点:
- 热点数据失效。热点数据是指网站中一些频繁访问的数据,当这些数据在缓存中被删除或者过期时,就会导致大量的请求打到数据库上,从而引起缓存击穿现象。
- 动态ID查询。一些网站中使用自增ID等方式生成唯一标识符,此类ID在缓存中不存在,若并发量极大且批量获取这些ID时容易造成缓存击穿。
- 缓存穿透攻击。恶意用户可能会故意访问某些不存在的key,从而导致缓存服务器和数据库进行不必要的查询操作。
造成Redis缓存击穿的原因主要包括以下几点:
- 热点数据失效。热点数据是指网站中一些频繁访问的数据,当这些数据在缓存中被删除或者过期时,就会导致大量的请求打到数据库上,从而引起缓存击穿现象。
- 动态ID查询。一些网站中使用自增ID等方式生成唯一标识符,此类ID在缓存中不存在,若并发量极大且批量获取这些ID时容易造成缓存击穿。
- 缓存穿透攻击。恶意用户可能会故意访问某些不存在的key,从而导致缓存服务器和数据库进行不必要的查询操作。
缓存并发
这里的并发指的是多个redis的client同时set key引起的并发问题。
可以将多个client并发操作,按照先到先执行的原则,先到的先执行,其余的阻塞。
当然,另外的解决方案是把redis.set操作放在队列中使其串行化,必须的一个一个执行。
缓存预热
缓存预热是指在系统上线后,提前将相关的缓存数据直接加载到缓存系统,避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题。
有了缓存预热后,系统刚上线用户也可以直接查询实现被预热的缓存数据。
缓存预热的解决方案:
- 直接写个缓存刷新页面,上线时手工操作下。
- 数据量不大,可以在项目启动的时候自动进行加载。
- 定时刷新缓存。
以上就是Redis缓存详解,主要谈到了雪崩、预热、降级等的介绍。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》