Redis做缓存使用,则必须对key做失效时间设置
失效策略一般选择:LRU、LFU
设置有过期时间的key中LRU(最近最少使用)、LFU(最少使用)
过期后主动删除
每秒调用10次,每次20个key,将过期的key删除,过期的key超过25%时,则重复上面的过程,直到过期的key低于25%
本文主要是为新手介绍一些基础概念,和常规解决思路
击穿
概念:击穿是,当Redis中的一个key失效后,同时有大量的请求用这个值,会导致这些请求都会压到DB中。
解决:因Redis的单进程单实例当从Redis中获取到空后,向Redis中用setnx的方式设置一个带有效期的key,只有第一个执行的请求会成功,其余的都会失败。失败的请求,都sleep进入休眠,然后递归调用从Redis中获取值的方法;成功的请求去DB中获取数据,同时还需要起一个守护线程,当去DB中获取数据未完成时,守护线程需要去延迟Redis中key的失效时间。当从DB中成功获取数据后,更新到Redis中。热点key不设置过期时间。
穿透
概念:穿透是,请求Redis和后端DB中不存在的值,白白浪费DB的资源。
解决:使用布隆过滤器,可以有3种方式:
1, 可以将布隆算法和记录的数组都放在server中;
2, 可以将布隆算法放在server中,记录的数组放在Redis的bitmap中;
3, 可以使用Redis的布隆过滤器。
缺点:1,删除DB中的数据后,不能删除布隆记录数组中的数据。可以考虑使用布谷鸟过滤器。
2,无效请求数据碰巧穿过了布隆过滤器的话,在DB中查不到结果时,可以在Redis中设置一个空key。
雪崩
概念:雪崩是,Redis中有大量的key同时失效,导致的DB访问压力增加。
解决:过期时间分散,随机过期时间;但是还有零点过期等问题,这时候可以使用击穿的解决方案处理。可以提前拿到数据的话,可以采用预加载。热点key不设置过期时间。
分布式锁
还是上面击穿的那一套方案,但是不完美,最终方案还得靠zookeeper、redisson。
Redisson分布式锁原理请查看另一篇文档。https://blog.csdn.net/jt781861965/article/details/118842024
setnx的其他写法
详解可参考https://www.cnblogs.com/wangyingshuo/p/14510524.html
1、加锁
加锁实际上就是在redis中,给Key键设置一个值,为避免死锁,并给定一个过期时间。
SET lock_key random_value NX PX 5000
值得注意的是:
random_value 是客户端生成的唯一的字符串。
NX 代表只在键不存在时,才对键进行设置操作。
PX 5000 设置键的过期时间为5000毫秒。
这样,如果上面的命令执行成功,则证明客户端获取到了锁。
2、解锁
解锁的过程就是将Key键删除。但也不能乱删,不能说客户端1的请求将客户端2的锁给删除掉。这时候random_value的作用就体现出来。
为了保证解锁操作的原子性,我们用LUA脚本完成这一操作。先判断当前锁的字符串是否与传入的值相等,是的话就删除Key,解锁成功。