目录
前言
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。在生产环境中,会因为很多的原因造成访问请求绕过了缓存,都需要访问数据库持久层,虽然对Redsi缓存服务器不会造成影响,但是数据库的负载就会增大,使缓存的作用降低。一个Redis实例可以支持万级别的并发请求,而单个数据库只能支持千级别的并发请求。两者处理请求并发能力相差十倍,数据库会由于压力过大而导致雪崩。
一、概念理解
缓存雪崩是指缓存服务器集群中某些服务器发生故障或宕机,导致缓存中大部分数据失效,而流量依然持续到来,导致数据库压力极大,最终导致系统崩溃的过程。缓存雪崩被认为是缓存失效所产生的连锁反应,它所造成的影响往往是灾难性的,会直接导致系统不可用,当缓存失效时,请求会全部流向后端数据库,造成数据库压力瞬间剧增,如果无法及时处理,很可能导致整个系统崩溃。
二、解决方案
1.缓存层高可用
可以把缓存层设计成高可用的,即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务。利用sentinel或cluster实现。增加缓存服务器的容错机制,如数据备份,服务器冗余等,可以防止单个缓存服务宕机导致整个缓存失效。
2.做二级缓存,或者双缓存策略
采用多级缓存,本地进程作为一级缓存,redis作为二级缓存,不同级别的缓存设置的超时时间不同,即使某级缓存过期了,也有其他级别缓存兜底
3.数据预热
为避免缓存服务器宕机后,所有请求都会直接访问数据库,我们可以通过缓存reload机制,预先将数据库数据加载到缓存中,再即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
避免给数据设置相同的过期时间,在设置过期时间时,增加一点随机值。
setRedis(key,value,time+Math.random()*10000);
4.缓存数据分级管理
对于缓存中的数据,我们可以将其分为热点数据和非热点数据,热点数据应该被频繁的访问和刷新,而非热点数据则可以更长时间的保存。对于不同级别的数据可以使用不同的缓存策略,以便更好的处理不同类型的访问。
5.服务器监控
对redis所在的服务器进行指标监控,比如QPS、CPU使用率、内存使用率等,如果发现redis服务宕机,而数据库请求压力倍增,此时可以启动熔断机制,暂停对缓存和数据库的访问,比如使用Hystrix服务熔断。
6.请求限流
请求限流,就是限制前端请求每秒请求量,使得数据库能承受前端全部请求。比如前端允许每秒访问1000次,其中900请求缓存,100次才请求数据库。一旦发生雪崩,数据库每秒请求激增到1000次,此时启动请求限流,在前端入口只允许每秒请求100次,过多的请求直接拒绝。
7.加锁排队
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。