1.Redis 的过期策略以及内存淘汰机制
Redis 采用的是定期删除+惰性删除策略+内存淘汰机制。
定期删除,Redis 默认每个 100ms 检查,是否有过期的 Key,有过期 Key 则删除。Redis 不是每个 100ms 将所有的 Key 检查一次,而是随机抽取进行检查(如果每隔 100ms,全部 Key 进行检查,Redis 岂不是卡死)。因此,如果只采用定期删除策略,会导致很多 Key 到时间没有删除。于是,惰性删除派上用场。
也就是说在你获取某个 Key 的时候,Redis 会检查一下,这个 Key 如果设置了过期时间,那么是否过期了?如果过期了此时就会删除。
如果定期删除没删除 Key。然后你也没即时去请求 Key,也就是说惰性删除也没生效。这样,Redis的内存会越来越高。那么就应该采用内存淘汰机制。
内存淘汰机制:(当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 Key)
2.Redis 和数据库双写一致性问题
读: 读redis->没有,读MySQL->把mysql数据写回redis
写: 写mysql->成功,写redis。
一.先删缓存,再更新数据库
(1)请求A进行写操作,删除缓存
(2)请求B查询发现缓存不存在
(3)请求B去数据库查询得到旧值
(4)请求B将旧值写入缓存
(5)请求A将新值写入数据库
采用延时双删策略:(1)先淘汰缓存(2)再写数据库(这两步和原来一样)(3)休眠1秒(这个时间根据业务去判断多久合适),再次淘汰缓存
二.先更新数据库,再删缓存(推荐!!!)
如果删除缓存失败(
(1)更新数据库数据;)
(2)缓存因为种种问题删除失败
(3)将需要删除的key发送至消息队列
(4)自己消费消息,获得需要删除的key
(5)继续重试删除操作,直到成功)
3.缓存穿透
即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。
解决方案
利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试。
采用异步更新策略,无论 Key 是否取到值,都直接返回。Value 值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的 Key。迅速判断出,请求所携带的 Key 是否合法有效。如果不合法,则直接返回。
4.缓存雪崩
即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。
给缓存的失效时间,加上一个随机值,避免集体失效。