缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级
Redis做缓存是因为Redis访问快,如果客户端在Redis中找得到目标数据,那就不去mysql找了,分担了mysql压力,实现高并发要求
一般缓存都是用户发起一次请求之后,再将该数据加载到缓存(并为该缓存expire一个有效期)
但是缓存实现高并发会出现一堆问题
缓存过期策略
缓存过期可以采用
①主动检查(默认每秒扫描10遍,且使用贪心策略一轮随机检查20个key,超过1/5过期就继续检查,直到轮数上线)
②惰性检测(用到再判断是否过期)
(从服务器是根据主服务器的指令进行操作,不会自己判断过期)
缓存淘汰策略
当redis缓存空间不够用(超maxmemory设置),这时候ram放不下的数据就会放到磁盘,发生RAM和磁盘数据的频繁交换,这样极大影响效率,所以要淘汰 一些即使没有过期的key
以下为淘汰方法:
noeviction:停止写请求
FIFO:最先缓存的最先过期:
LFU:最少频率使用
LRU:最近最少使用
ttl:key的剩余寿命ttl越小越先被淘汰
random:随机淘汰
缓存更新策略
①Cache aside:由客户端自己负责写redis缓存还是写mysql数据库(先访问redis,找不到,再去mysql取数据,然后放到缓存中)
②Read Through:用户请求的时候,若redis服务器没有缓存,则由redis缓存服务器负责去mysql数据库服务器拿数据来更新缓存
③Write Through:和Read Through一样是由redis缓存服务器负责与mysql交道,只不过发生在用户更新数据时候
④Write Behind Caching Pattern:Write Through,且redis是异步更新mysql的
第②③④策略下,对于客户端而言,redis和mysql是一个整体,不用管谁是谁,缓存细节被隐藏了
缓存雪崩
【缓存失效】,导致所有本来应该查询redis缓存的请求全部取查后端mysql数据库了,造成mysql数据库压力过大崩盘
造成缓存失效的可能性很多,比较多的一种是原有缓存失效,而新缓存还没有储存到redis缓存中(比如大量缓存同时过期),如果是使用普通的hash定位服务器方法也会造成缓存失效。这样会瞬间给mysql造成巨大压力而崩盘。
解决:
①避免缓存大量同时过期解决:比如缓存过期时间随机
②在新缓存就位之前,临时储存失效缓存:这样请求来了,新缓存还没到,就先直接返回临时缓存,而不是直接过期丢弃之
③防止过多请求同时访问数据库:加锁队列,但这样就没法高并发了,并没有解决实际问题,所以不会用在高并发环境中
缓存穿透
对于数据库没有的数据,每次用户请求的就要先查redis缓存,返回空,然后去mysql查,又返回空,如果大量这样的请求存在,那就造成了缓存穿透,增加系统负荷
解决:
①布隆过滤器:将所有可能的数据存在一个布隆过滤器中(一个很大的bitmap),布隆过滤器可以快速判断出一定不存在的数据,进而直接拦截,不进行在系统中查询
②缓存不存在的key:那么第二次相同key来查,redis就返回一个默认值告诉他没有,那也就不会继续访问数据库了
缓存预热
开机的时候,不必等用户第一次访问数据库再将数据加载到缓存,而是预热一部分数据直接加载到缓存
缓存降级
弃车保帅,降级非核心业务缓存,保证核心业务缓存