Redis学习笔记 - 过期键删除策略

参考:<<Redis设计与实现>>

  • 注:这本书是基于Redis3.0版本写的,和后面的版本有点差异

一、过期键删除策略

一个键过期了,什么时候它会被删除?可能有以下三种策略:

  • 定时删除:在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作
  • 惰性删除:放任键过期不管,每次从键空间获取键时,检查取得的键是否过期,如果过期的话,就删除该键;没有过期,就返回该键
  • 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于检查多少数据库、删除多少键,由算法决定。

注:第一种、第三种为主动删除策略,第二种为被动删除策略

1.1 定时删除

优缺点:

  • 优点:内存压力小,通过使用定时器,定时删除策略可以保证过期的键会尽可能快地被删除,并释放过期键占用的内存
  • 缺点:
    • CPU压力大,过期键比较多的时候,删除过期键这一行为可能会占用相当一部分的CPU时间,在内存不紧张但CPU紧张情况下,将CPU资源用在删除和当前任务无关的过期键上,会对服务器的响应时间和吞吐量造成影响。
    • 创建一个定时器要用到Redis服务器的时间事件,当前时间事件的实现方式为无序链表,查找一个事件的事件复杂度为O(N),当创建大量的定时器情况下,不能高效的处理大量时间事件。
1.2 惰性删除

(1)优缺点

  • 优点:CPU压力小,程序只会在取出键时才会对键进行过期检查,并且删除目标仅限于当前处理的键,不会在其他无关的过期键上花费CPU时间。
  • 缺点:内存压力大,一个键过期,但仍保留在数据库中,只要这个过期键不被删除,它所占用的内存就不会释放。

(2)示例

例如一些和时间有关的数据,比如日志(log),在某个时间点后,对它们基本不访问,这类过期数据大量积压在数据库中,用户以为已经被服务器删除,但仍然存在,键所占的内存也没有被释放。

这种情况有内存泄漏风险,对于像Redis这种非常依赖于内存的服务器来说,肯定是不行的。

1.3 定期删除

(1)定时删除和惰性删除的这种方案 ---- 定期删除

从1.1和1.2可知,单独使用定时删除、惰性删除都有明显的缺陷:

  • 定时删除占用太多CPU,影响服务器的响应时间和吞吐量
  • 惰性删除浪费太多内存,有内存泄漏风险

定期删除是这两种策略的一种折中:

  • 定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响
  • 通过定期删除过期键,定期删除策略有效地减少了因为过期键而带来的内存浪费

(2)过期策略的难点

定期删除策略的难点是确定删除操作的时长和频率:

  • 如果删除操作执行得太频繁,或者执行时间太长,定期删除策略就会退化成定时删除策略,以至于将CPU时间过多地消耗在删除过期键上
  • 如果删除操作执行太少,或执行时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存的情况

二、Redis的过期键删除策略

Redis中实际使用的是惰性删除和定期删除两种策略。通过配合使用这两种删除策略,服务器可以很好的合理使用CPU时间和避免浪费内存空间之间取得平衡。

2.1 惰性删除策略的实现

实现流程:

  • 执行命令前调用expireIfNeeded()函数对输入键进行检查
  • 如果键已经过期,那么expireIfNeeded()函数会把输入键从数据库删除
  • 如果键未过期,expireIfNeeded()函数不做任何处理

注:参考源码中的db.c文件,https://github.com/antirez/redis/blob/3.0/src/db.c

命令调用expireIfNeeded()函数流程如下图所示:
调用expireIfNeeded()函数流程

2.2 定时删除策略的实现

实现流程:

  • Redis服务器周期性调用activeExpireCycle()函数
  • 在规定时间内,分多次遍历服务器中的各个数据库,随机检查数据库中的一部分键的过期时间,并删除其中的过期键

activeExpireCycle()函数说明:

  • 该函数每隔100ms被调用一次
  • current_db参数记录最后测试的数据库,下次执行时从下一个数据库执行,如果所有数据库都已经执行,那么current_db重置为0,开始新一轮检查工作
  • 每次只是随机检查一部分键的过期时间,然后删除
  • 该函数接收一个type参数,支持两种模式:ACTIVE_EXPIRE_CYCLE_FAST和ACTIVE_EXPIRE_CYCLE_SLOW,用于控制执行时间

注:参考源码中redis.c文件的说明,https://github.com/antirez/redis/blob/3.0/src/redis.c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值