Redis基础系列(八)——过期键删除策略

855 阅读3分钟

这是我参与更文挑战的第26天,活动详情查看:更文挑战

Redis 设置键过期时间的命令

/**
* 将key 的值设置为 value,并将 key 的过期时间设为 seconds (以秒为单位)。
* 只适用于String对象
*/
SETEX key seconds value 

/**
* 这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,
* 而不是像 SETEX 命令那样,以秒为单位。
* 只适用于String对象
*/
PSETEX key milliseconds value

//将键 key 的生存时间设置为 seconds 秒
EXPIRE key seconds    
    
//将键 key 的生存时间设置为 milliseconds 毫秒
PEXPIRE key milliseconds 
    
//将键 key 的过期时间设定为 timestemp 指定的秒数时间戳
EXPIREAT key timestemp 
    
//将键 key 的过期时间设定为 milliseconds-timestemp 指定的秒数时间戳
PEXPIREPAT key milliseconds-timestemp 

  以上六种设置键过期的方式,其中 SETEXPSETEX两个命令只适用于字符串对象,其他4个命令适用于所有键类型。虽然有很多不同的命令可以设置键过期,但是最终其他的命令都会被转为通过 PEXPIREPAT 命令实现。

过期键删除策略

  通过设置键的过期时间,可以判断某个时间点一个键是否过期。对于已过期的键,还需要将其删除,删除的策略有三种:

  • 定时删除:在设置键的过期时间时,创建一个定时器,让定时器在键过期的时候,立即执行对键的删除操作。
    • 优点:对内存最友好,应删尽删
    • 缺点:对CPU不友好,在过期键较多的情况下,定时器会占用太多的CPU资源
  • 惰性删除:放任过期键不管,每次从键空间中获取键时,都检查取得的键是否过期,如果过期则将其删除并返回nil,如果键不过期则返回键。
    • 优点:对CPU友好,只在用到键的时候才判断是否过期
    • 缺点:对内存不友好,如果一个过期键没有再被用到,也就会一直留在内存中
  • 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。
    • 对定时删除和定期删除进行整合和折中,同时减轻CPU和内存的消耗
    • 难点:如何确定删除操作执行的时长和频率,执行得太频繁或者执行时间太长会退化为定时删除,执行得太少则退化为惰性删除

Redis 过期键删除策略

  Redis 中采用惰性删除和定期删除配合的策略,实现合理使用CPU时间和避免浪费内存空间之间取得平衡。

Redis 中,对于设置了过期时间的键,每次读写键时都会调用expireNeeded函数判断键是否过期。

惰性删除策略模式如下:

惰性删除策略.png

定期删除策略

  • 每隔一段时间,Redis会用规定的时间片段,从指定数据库中取出一定数量的键进行检查是否过期
  • 使用 current_db 记录当前的检查的数据库(一个Redis服务器中可以有多个数据库,通过 select 命令指定当前使用的数据库)
  • 当所有数据库都被检查一遍之后,current_db 被设置为0,下一次从0号数据库开始重新检查