Redis(三十三)-Redis键过期时间设置以及过期键删除策略

您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦
💪🏻 1. Python基础专栏,基础知识一网打尽,9.9元买不了吃亏,买不了上当。 Python从入门到精通
❤️ 2. Python爬虫专栏,系统性的学习爬虫的知识点。9.9元买不了吃亏,买不了上当 。python爬虫入门进阶
❤️ 3. Ceph实战,从原理到实战应有尽有。 Ceph实战
❤️ 4. Java高并发编程入门,打卡学习Java高并发。 Java高并发编程入门
😁 5. 社区逛一逛,周周有福利,周周有惊喜。码农飞哥社区,飞跃计划
全网同名【码农飞哥】欢迎关注,个人VX: wei158556

键的过期时间如何设置?

在Redis中我们可以通过四个不同的命令来给键设置过期时间,分别是:

  1. EXPIRE <key> <ttl> 命令用于将键key的生存时间设置成ttl秒。(TTL的意思是 Time To Live)
  2. PEXPIRE <key> <ttl> 命令将键key的生存时间设置成ttl毫秒。
  3. PEXPIREAT <key> <timestamp> 命令用于将键key的过期时间设置为timestamp锁所指定的秒数时间戳。
  4. PEXPIREAT <key> <timestamp> 命令用于将键key的过期时间设置为timestamp所指定的毫秒数时间戳。
    虽然有多种不同单位和不同形式的设置命令,但实际上EXPIRE、PEXPIRE、EXPIREAT三个命令都是使用PEXPIREAT命令来实现的。无论客户端执行的是以上四个命令中的哪一个,经过转换之后,最终的执行结果都和执行PEXPIREAT命令一样。

过期时间如何保存?

redisDb结构的expires字典保存了数据库中所有键的过期时间,我们称这个字典为过期字典,过期字典的键是一个指针,这个指针指向键空间中的某个键对象(也即是某个数据库键),键空间的键和过期字典的键都是指向同一个键对象。另外,过期字典的值是一个long long类型的整数,这个整数保存了键所指向的数据库键的过期时间,该过期时间是一个毫秒精度的UNIX的时间戳。
在这里插入图片描述
这里的时间戳 1600341444018 表示到 2020-09-17 19:20:30秒是键message的过期时间。

过期键如何判定呢?

检查一个键是否过期的判定步骤主要有两步:

  1. 检查给定键是否存在于过期时间,如果存在,那么取键的过期时间。
  2. 检查当前UNIX时间戳是否大于键的过期时间,如果是的话,那么键已经过期,否则键未过期。
    用伪代码描述如下:
   def is_expired(key):
   		#取得键的过期时间
		expire_time_in_ms=redisDb.expries.get(key)
		#键没有设置过期时间
		if expire_time_in_ms is None: 
				return false
		#取得当前时间的UNIX时间戳
		now_ms=get_current_unix_timestamp_in_ms()
		#检查当前时间是否大于键的过期时间
		if now_ms>expire_time_in_ms:
				#是,键已经过期
				return true
		else:
			#否,键未过期
			return false

实现过期键判定的另一种方法是使用TTL命令或者PTTL命令,比如说,如果对某个键执行TTL命令,并且命令返回的值大于等于0,那么说明该键未过期,在实际中,Redis检查键是否过期的方法和is_expireed函数所描述的方法一致,因为直接访问字典比执行一个命令稍快一些。

如何删除带过期时间的键?

通过前面的介绍,我们知道了数据库键的过期时间都是保存在过期字典中,又知道了如何判断一个键是否过期,现在有个问题是,当键过期是否,是否会立即删除?Redis有三种过期键删除策略。

  1. 定时删除:在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。这种策略可以保证过期键会被尽快地被删除,并释放过期键所占用的内存。但是它对CPU时间是最不友好的,在过期键比较多的情况下,删除过期键这一行为可能会占用相当一部分CPU时间,无疑会对服务器的响应时间和吞吐量造成影响。

  2. 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都会检查取得的键是否过期,如果过期的话,就会删除该键,如果没有过期,就返回该键。该策略对CPU时间来说是最友好的,程序只会在取出键时才会对键进行过期检查,这可以保证删除过期键的操作只会在非做不可的情况下进行。但是它的缺点就是对内存是最不友好的,如果一个键已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会被释放。

  3. 定期删除:每隔一段时间(默认是每隔100ms,在配置文件中由hz参数控制,取值范围是1~500),会扫描一定数量的数据库的expires字典中的一定数量的key。并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。它具体的清理过程是:

    • 遍历所有的db
    • 从过期字典的key的集合中随机检查20个key
    • 删除检查中发现的所有过期key
    • 如果检查结果中25%以上的key已过期,则继续重复执行步骤2和步骤3,否则继续遍历下一个db。
      调大hz将会提高redis定期任务的执行频率,如果你的redis中包含很多过期key的话,可以考虑将这个值调大,但要注意同时也会增加CPU的压力,redis作者建议这个值不要超过100。

Redis中同时使用了惰性过期和定期过期两种过期策略。

Redis的内存淘汰策略

当使用内存大于maxmemory时,就会触发Redis主动淘汰内存方式:

  1. volatile-lru:利用LRU算法移除设置过过期时间的key(LRU:最近使用Least Recently Used),例如:有个是3个key,a最近10分钟使用了100次,b最近10分钟使用了50次,c最近一个小时使用了1次,那么会淘汰掉c。
  2. allkeys-lru: 利用LRU算法移除任何key(和上一个相比,删除的key包括设置过期时间的和不设置过期时间的),通常使用该方式
  3. volatile-random:移除设置过过期时间的随机key;
  4. allkeys-random:无差别的随机移除
  5. volatile-ttl:移除即将过期的key(minor TTL)
  6. noeviction:不移除任何key,只是返回一个写错误,默认选项,一般不会选用。
    可以通过设置 maxmemory-policy 来设置内存淘汰方式:

aof/rdb和复制功能对过期键的处理

rdb

  • 生成rdb文件: 生成时,程序会对键进行检查,过期键不会放入rdb文件。
  • 载入rdb文件:载入时,如果以主服务器模式运行,程序会对文件中保存的键进行检查,未过期的键会被载入到数据库中,而过期键则会忽略;如果以从服务器模式运行,无论键过期与否,均会载入数据库中,过期键会通过与主服务器同步而删除。

aof

  • 当服务器以aof持久化模式运行时,如果数据库中某个键已经过期,但它还没有被删除,那么aof文件不会因为这个过期键而产生任何影响;当过期键被删除后,程序会向aof文件追加一条del命令来显式记录该键已被删除。
  • aof重写过程中,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的aof文件中。

复制

当服务器运行在复制模式下时,从服务器的过期删除动作由主服务器控制:

  1. 主服务器在删除一个过期键后,会显式地向从服务器发送一个del命令,告知从服务器删除这个过期键;
  2. 从服务器在执行客户端发送的读命令时,即使碰到过期键也不会将过期键删除,而是继续像处理未过期的键一样来处理过期键;
  3. 从服务器只有在接到主服务器发来的del命令后,才会删除过期键。

总结

本文主要从Redis键过期时间的设置,过期时间的保存以及过期键的删除策略四个方面对Redis中键过期时间进行了阐述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农飞哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值