Redis 的过期策略
Redis是用内存作缓存,所以只是起到暂时储存数据的作用,提高访问速度和并发量,内存有限,所以需要制定过期策略,过期的数据清除腾出空间给新的数据
1.定期删除
所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。
假如你放了10w个数据,如果每次都去遍历它们是否过期,那会造成很大的cpu负载的,所以定期删除,只是随机检查一些,但这样会导致本来过期的key没能被及时检查到过期了,所以有了惰性删除。
2.惰性删除
惰性删除的策略是每次获取时会检查key是否过期,过期就删除不返回。
但是同样会有问题,如果大量key过期没被定期删除,并且也没被访问而惰性删除,就会造成内存不足,所以有了内存淘汰机制。
内存淘汰机制
1.noeviction
不删除key,当内存满了就报错。
2.volatile-lru
对于设置了过期的key中删除最近最少使用的key。
3.volatile-ttl
对于设置了过期时间的key,删除离当前时间最近的key。
4.volatile-random
对于设置了过期时间的key,随机删除key。
5.allkeys-random
对于全部的key进行随机删除。
6.allkeys-lru(推荐)
对于全部的key进行lru删除。
redis 雪崩 击穿 穿透
雪崩问题
有一批热点key在同一时间内过期,如果处于访问高峰,有大批请求就会到达数据库,造成数据库宕机。
(可以通过设置过期时间为随机值,一定程度上解决)
缓存雪崩的事前事中事后的解决方案如下。
事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。
事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
穿透问题
恶意攻击,通过访问一个一定不存在的key,每次都把请求打到数据库,造成数据库宕机。
解决方案主要可以从两个方面
- 在应用级别上将不可能存在的key过滤掉
- 无法过滤掉的key采用value=null的值写入缓存中来应对这个key的请求,同时这个key的有效期可以设置短一些。
击穿问题
有一个热点key一直扛着高流量的访问,一旦过期,所有请求就会打到数据库上面,造成数据库宕机。
例如电商的爆款
问题的解决方案如下
- 如果热点key的数据更新不频繁或者不会发生更新,可设置为永久key,或者每一次请求都重置key的有效期。
- 如果数据频繁更新,可以使用定时线程或者数据库更新后主动更新缓存的策略来保证数据一致性。