Redis如何设置key的过期时间?

102

Redis如何实现键的过期?我从这里了解到,Redis存储键过期的时间,但具体是如何实现的呢?

3个回答

219
简而言之,对于每个 Redis 对象,都有一个过期时间。除非您将对象设置为过期,否则该时间将是“永远不过期”。
现在,过期机制本身是半惰性的。惰性过期意味着直到读取对象时才实际过期。在读取对象时,我们检查其过期时间戳,如果已经过期,则返回空值,并同时删除该对象。但问题在于,如果一个键从未被访问,它就会无缘无故地占用内存。
因此,Redis 添加了第二层随机主动过期机制。它会随机读取键,并在触碰到过期键时,根据惰性机制删除它。这不会影响过期行为,只是增加了过期键的“垃圾回收”。
当然,实际实现比这更复杂,但这是主要思想。
您可以在此处阅读更多信息:http://redis.io/commands/expire 活跃过期循环的源代码可以在此处找到:https://github.com/antirez/redis/blob/a92921da135e38eedd89138e15fe9fd1ffdd9b48/src/expire.c#L98

2
如果你喜欢简洁的方式,似乎可以监听事件,告诉你哪个已过期或被驱逐,这个计划之美在于它的简单性。但是,如果你想像对待人一样对待对象,并保存所有去除的键所包含的数据——你知道,将其序列化到数据库(或任何你想要的地方)上? - ruffin
Redis不会为新数据释放内存吗? - LCB
5
LCB并没有明确说明。顺便提一下,Redis 6将包括该机制的重大更改,因此这个答案很快只适用于旧版本的Redis。 - Not_a_Golfer
1
@Not_a_Golfer 请在 GitHub 上复制链接时使用 y 键。否则,随着时间的推移,它将指向其他内容。 - Valentin V
“eads random keys all the time” 这个意思是 Redis 在单独的线程或进程中执行吗?Redis 一直都是单线程的。 - piepi
@piepi 是的。Redis有几个实用程序线程在后台执行任务,但用户访问是在单个线程上进行的。 - Not_a_Golfer

34

对于Redis 6,从发布说明中可以看到:

Redis 6.0中的过期周期已被重写,以允许更快的过期,更接近生存时间(TTL)属性。Redis 6过期将不再基于随机采样,而是将按过期时间排序的键放入基数树中进行处理。
Redis 6发布说明

要获取完整的发布说明,请单击此处


14

参考文献中得知:

Redis的键有两种过期方式:被动方式和主动方式。

当某个客户端尝试访问一个已超时的键时,这个键就会被 passively expired。

当然仅此是不够的,因为有一些已经超时的键可能再也不会被访问到。因此,Redis 会定期随机测试一些带有过期时间的键,无论这些键是否被访问过,都将它们设置为过期状态并从 key空间中删除这些已过期的键。

具体来说,Redis 每秒钟执行以下操作10次:

从带有 expire 属性的键集合中随机选择20个键进行测试,删除所有已过期的键。如果过期键的数量超过25%,则重新从第1步开始执行。这是一种简单的概率算法,基本上假设我们的样本代表整个键空间,我们会继续过期操作,直到可能已过期的键的百分比低于25%。

这意味着在任何给定时刻,使用内存的已过期最大键数等于每秒最大写入操作数除以4。

  • 复制链接和AOF文件中如何处理过期键

  • 3
    更新:Redis 6.0中的过期循环已被重写,以允许更快速的过期操作,更接近生存时间(TTL)属性。Redis 6的过期将不再基于随机抽样,而是按过期时间在基数树中排序键。 - Amin Shojaei

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接