您现在的位置是:首页 >技术交流 >Redis—过期删除策略网站首页技术交流
Redis—过期删除策略
Redis是可以对键值设置过期时间的,那么相对而产生过期删除策略
一、如何判定key是否过期
每当我们对一个 key 设置了过期时间时,Redis 会把该 key 带上过期时间存储到一个过期字典。
过期字典(其实是一个哈希表,为了支持o(1)查询)存储在 redisDb 结构中
typedef struct redisDb {
dict *dict; /* 数据库键空间,存放着所有的键值对 */
dict *expires; /* 键的过期时间 */
....
} redisDb;
//过期字典expires的key是一个指针(指向键对象)
//过期字典expires的value是一个long long类型整数,表示过期时间
每次在Redis中查询一个key值时,会先判断是否在过期字典中,如果在,先判断是否过期!
二、过期删除策略
先说常见的过期删除策略
一共有三种
1. 定时删除
2. 惰性删除
3. 定期删除
定时删除 | 惰性删除 | 定期删除 | |
方法 | 设置定时器,到时删除 | 过期不删除,再次访问时候检查 | 每隔⼀段时间对⼀部分键进行检查 |
优点 | 对内存优化 | 对CPU友好 | 减少了对CPU的影响,释放部分内存 |
缺点 | 对CPU不友好 | 对内存不友好,造成内存泄露 | 难以衡量定时时⻓ |
三、Redis过期删除策略
Redis实际使用:惰性删除+定期删除
1. Redis惰性删除实现是靠 expireIfNeeded 函数对其进行检查
如果过期就选择异步或者同步删除
没过期就返回对应键值
2. Redis定期删除是每隔一段时间,随机从Redis数据库中抽取一定数量进行过期删除
具体实现是
do {
//已过期的数量
expired = 0;
//随机抽取的数量
num = 20;
while (num--) {
//1. 从过期字典中随机抽取 1 个 key
//2. 判断该 key 是否过期,如果已过期则进行删除,同时对 expired++
}
// 超过时间限制则退出
if (timelimit_exit) return;
/* 如果本轮检查的已过期 key 的数量,超过 25%,则继续随机抽查,否则退出本轮检查 */
} while (expired > 20/4);
四、Redis内存淘汰策略
1、不进行数据淘汰的策略
noeviction(Redis3.0之后,默认的内存淘汰策略) :它表示当运行内存超过最大设置内存时,不淘汰任何数据,这时如果有新的数据写入,则会触发 OOM,但是如果没用数据写入的话,只是单纯的查询或者删除操作的话,还是可以正常工作。
2、进行数据淘汰的策略
针对「进行数据淘汰」这一类策略,又可以细分为「在设置了过期时间的数据中进行淘汰」和「在所有数据范围内进行淘汰」这两类策略。
在设置了过期时间的数据中进行淘汰:
- volatile-random:随机淘汰设置了过期时间的任意键值;
- volatile-ttl:优先淘汰更早过期的键值。
- volatile-lru(Redis3.0 之前,默认的内存淘汰策略):淘汰所有设置了过期时间的键值中,最久未使用的键值;
- volatile-lfu(Redis 4.0 后新增的内存淘汰策略):淘汰所有设置了过期时间的键值中,最少使用的键值;
在所有数据范围内进行淘汰:
- allkeys-random:随机淘汰任意键值;
- allkeys-lru:淘汰整个键值中最久未使用的键值;
- allkeys-lfu(Redis 4.0 后新增的内存淘汰策略):淘汰整个键值中最少使用的键值。
五、Redis持久化时,过期键处理策略?
▪ AOF
• AOF写⼊阶段:该值还没有被删除,保留过期键;真正删除时候追加⼀条DEL命令
• AOF重写阶段:已过期的键不会被保存到重写后的AOF⽂件中
▪ RDB
• RDB⽣成阶段:对key进⾏检查,过期的key不会被载⼊到数据库中
• RDB加载阶段:
◦ 主服务器:载⼊时候,会对key进⾏检查,过期时候不会被加载到数据库中
◦ 从服务器:⽆论是否过期都会被载⼊(主从服务器同步时候,从服务器数据会被清空,所以过期键写到从服务器影响不大)
六、Redis主从模式中,过期键处理策略?
▪ 从库对过期键删除是被动的(从库读到过期键还是会返回),主库key到期时候,在AOF中追加⼀条DEL命令,同步到所有从库