【文档熟肉】Redis的过期时间EXPIRE

EXPIRE key seconds [NX|XX|GT|LT]

Available since 1.0.0.
(该命令)从1.0.0版本可用。

Time complexity: O(1)
时间复杂度:O(1)

Set a timeout on key. After the timeout has expired, the key will automatically be deleted. A key with an associated timeout is often said to be volatile in Redis terminology.
在key上设置过期。在过期后,key会自动删除。在Redis中,一个过期的key是很容易消失的。

The timeout will only be cleared by commands that delete or overwrite the contents of the key, including DEL, SET, GETSET and all the *STORE commands. This means that all the operations that conceptually alter the value stored at the key without replacing it with a new one will leave the timeout untouched. For instance, incrementing the value of a key with INCR, pushing a new value into a list with LPUSH, or altering the field value of a hash with HSET are all operations that will leave the timeout untouched.
只有删除或者key内容的重新写入这样的命令才能清除过期(的key),包括DELSETGETSET和所有*STORE命令。这意味着,从概念上讲,所有变更key的值的操作都会使它(key)清除。例如,使用INCR使一个key的value增加,使用LPUSH向一个list中添加新的值,或者使用HSET改变一个哈希的值,所有这些操作都会使它(过期的key)删除。

The timeout can also be cleared, turning the key back into a persistent key, using the PERSIST command.
也可以清除过期时间,使用PERSIST命令把一个key变成一个永久的Key。

If a key is renamed with RENAME, the associated time to live is transferred to the new key name.
如果一个key使用RENAME重命名了,相关的过期时间会转移到新命名的key身上。

If a key is overwritten by RENAME, like in the case of an existing key Key_A that is overwritten by a call like RENAME Key_B Key_A, it does not matter if the original Key_A had a timeout associated or not, the new key Key_A will inherit all the characteristics of Key_B.
如果一个key被RENAME重写了,例如一个存在的key Key_A被重写RENAME Key_A Key_B,原来的Key_A存在相关的过期时间或者永久的是无所谓的,新的key Key_B会继承Key_A的状态。(文档是写错了吧,RENAME后第一个key才是旧的key,翻译已修改)

Note that calling EXPIRE/PEXPIRE with a non-positive timeout or EXPIREAT/PEXPIREAT with a time in the past will result in the key being deleted rather than expired (accordingly, the emitted key event will be del, not expired).
注意,带有负数过期时间的 EXPIRE/PEXPIRE或者时间为过去的 EXPIREAT/PEXPIREAT 会导致key在过期前被删除(相应的,发生的key事件是删除而不是过期)

Options

操作

The EXPIRE command supports a set of options:
EXPIRE命令支持下列操作:

  • NX – Set expiry only when the key has no expiry
    NX:只有key没有设置过期时间时,才能设置过期时间

  • XX – Set expiry only when the key has an existing expiry
    只有key存在过期时间时,才能设置过期

  • GT – Set expiry only when the new expiry is greater than current one
    只有新设置的过期时间比当前的(过期时间)更大,才能设置过期时间

  • LT – Set expiry only when the new expiry is less than current one
    只有新设置的过期时间比当前的(过期时间)更小,才能设置过期时间

A non-volatile key is treated as an infinite TTL for the purpose of GT and LT. The GT, LT and NX options are mutually exclusive.
对于GT和LT操作来说,一个没有过期时间的key可以视为具有永久的TTL(生存时间)。GT、LT和NX操作不能一起使用。

Refreshing expires

刷新过期时间

It is possible to call EXPIRE using as argument a key that already has an existing expire set. In this case the time to live of a key is updated to the new value. There are many useful applications for this, an example is documented in the Navigation session pattern section below.
在一个key已经存在过期时间的情况下是可以使用EXPIERE参数的。在这种情况下,key的生存时间会被刷新为新的值。它有很多有用的地方,比如导航会话模式下的记录。

Differences in Redis prior 2.1.3

Redis 2.1.3之前版本的不同之处

In Redis versions prior 2.1.3 altering a key with an expire set using a command altering its value had the effect of removing the key entirely. This semantics was needed because of limitations in the replication layer that are now fixed.
Redis 2.1.3之前的版本,一个key的过期后,会自动删除该key。由于复制层中的限制(现在已经固定),这种语义是必需的。

EXPIRE would return 0 and not alter the timeout for a key with a timeout set.
EXPIRE如果没有成功改变key的过期时间会返回0。

Return value

返回值

Integer reply, specifically:
返回整形,明确的讲:

1 if the timeout was set.
如果过期时间设置上了,(会返回)1
0 if the timeout was not set. e.g. key doesn’t exist, or operation skipped due to the provided arguments.
如果过期时间没有设置上,例如key不存在或者由于添加的参数跳过了,(会返回)0

Examples

示例

redis> SET mykey "Hello"
"OK"
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10
redis> SET mykey "Hello World"
"OK"
redis> TTL mykey
(integer) -1
redis> EXPIRE mykey 10 XX
ERR ERR wrong number of arguments for 'expire' command
redis> TTL mykey
(integer) -1
redis> EXPIRE mykey 10 NX
ERR ERR wrong number of arguments for 'expire' command
redis> TTL mykey
(integer) -1
redis> 

Pattern: Navigation session

模式:导航会话

Imagine you have a web service and you are interested in the latest N pages recently visited by your users, such that each adjacent page view was not performed more than 60 seconds after the previous. Conceptually you may consider this set of page views as a Navigation session of your user, that may contain interesting information about what kind of products he or she is looking for currently, so that you can recommend related products.
假设您有一个web服务,您对您的用户最近访问的N个页面感兴趣,这样每个相邻页面的查看不会在前一个页面之后超过60秒。从概念上讲,您可以将这组页面视图视为用户的导航会话,该会话可能包含有关用户当前正在寻找的产品类型的有趣信息,以便您可以推荐相关产品。

You can easily model this pattern in Redis using the following strategy: every time the user does a page view you call the following commands:
你可以很容易地使用以下策略在Redis中建模这个模式:每次用户做一个页面视图,你调用以下命令:

MULTI
RPUSH pagewviews.user:<userid> http://.....
EXPIRE pagewviews.user:<userid> 60
EXEC

If the user will be idle more than 60 seconds, the key will be deleted and only subsequent page views that have less than 60 seconds of difference will be recorded.
如果用户将空闲超过60秒,该键将被删除,只有后续的页面查看有小于60秒的差异将被记录。

This pattern is easily modified to use counters using INCR instead of lists using RPUSH.
这个模式很容易修改为使用INCR使用计数器,而不是使用RPUSH使用列表。

Appendix: Redis expires

附录:Redis过期

Keys with an expire
带有过期时间的key

Normally Redis keys are created without an associated time to live. The key will simply live forever, unless it is removed by the user in an explicit way, for instance using the DEL command.
一般来说在创建key时没有设置生存时间。这个key一般来说会一直存在,除非它被用户通过某种明确的途径删除,例如使用DEL命令。

The EXPIRE family of commands is able to associate an expire to a given key, at the cost of some additional memory used by the key. When a key has an expire set, Redis will make sure to remove the key when the specified amount of time elapsed.
EXPIRE命令家族可以通过给这个key多消耗一些内存为代价,给一个指定的KEY设置过期时间。当这个key有一个过期时间时,Redis会在指定时间过去后删除key。

The key time to live can be updated or entirely removed using the EXPIRE and PERSIST command (or other strictly related commands).
key的生存时间可以通过expire和persist命令(或者其他相关的精准命令)来更新或者完全删除。

Expire accuracy
过期(时间)的精准性

In Redis 2.4 the expire might not be pin-point accurate, and it could be between zero to one seconds out.
在Redis2.4时,(key的)过期并不是完全精准的它可能有0s-1s的误差。

Since Redis 2.6 the expire error is from 0 to 1 milliseconds.
从Redis2.6开始,过期时间的误差被限制在0-1毫秒之间。

Expires and persistence
过期和持久化

Keys expiring information is stored as absolute Unix timestamps (in milliseconds in case of Redis version 2.6 or greater). This means that the time is flowing even when the Redis instance is not active.
key的过期时间信息以Unix的时间戳形式存储(以毫秒为单位,从Redis2.6版本或者更早开始)。它意味着甚至在Redis节点关闭的时候,(生存)时间(的统计)都是不间断的。

For expires to work well, the computer time must be taken stable. If you move an RDB file from two computers with a big desync in their clocks, funny things may happen (like all the keys loaded to be expired at loading time).
为了让过期很好的工作,计算机的时间必须是稳定的。如果你在两台时间不同步差异很大的计算机之间拷贝RDB文件,有趣的事情可能会发生(例如所有key在装载时就被加载为过期)

Even running instances will always check the computer clock, so for instance if you set a key with a time to live of 1000 seconds, and then set your computer time 2000 seconds in the future, the key will be expired immediately, instead of lasting for 1000 seconds.
即使在节点运行时依然会总会检查计算机的时钟,所以例如如果你设置了一个生存1000s的key,然后你将你的计算机的时钟调到了2000s后,那么你的key就会立即过期,而不是存在1000s。

How Redis expires keys
Redis的key是如何过期的

Redis keys are expired in two ways: a passive way, and an active way.
Redis的Key通过两种方式过期(并被删除):被动方式和主动方式。

A key is passively expired simply when some client tries to access it, and the key is found to be timed out.
一个key的被动过期通常是某些客户端尝试获取它时,会发现这个key过期了(随之删除)。

Of course this is not enough as there are expired keys that will never be accessed again. These keys should be expired anyway, so periodically Redis tests a few keys at random among keys with an expire set. All the keys that are already expired are deleted from the keyspace.
这样做当然是不够的,因为存在着不会被(客户端)访问的过期的key。这些key也应当过期,所以Redis会在具有过期时间的Key中定期的随机检验少数的key。所有的被发现过期的key都从key空间中删除了。

Specifically this is what Redis does 10 times per second:
具体的说,这就是Redis每秒处理10次的(动作):

1.Test 20 random keys from the set of keys with an associated expire.

  1. 从具有过期时间的key中,抽取20个随机的key检验。

2.Delete all the keys found expired.
2. 删除所有被发现过期的key。

3.If more than 25% of keys were expired, start again from step 1.
3. 如果超过25%的key都过期了,再次重复步骤1。

This is a trivial probabilistic algorithm, basically the assumption is that our sample is representative of the whole key space, and we continue to expire until the percentage of keys that are likely to be expired is under 25%
这是一个很简单的概率算法,基于假设样本具有整个key空间的代表性,并且我们会继续过期(key)直到过期的key的比率小于25%。

This means that at any given moment the maximum amount of keys already expired that are using memory is at max equal to max amount of write operations per second divided by 4.
这意味着在任何给定的时刻,已经过期的正在使用内存的键的最大数量等于每秒最大的写操作量除以4。

How expires are handled in the replication link and AOF file
在备份和AOF文件中如何处理过期

In order to obtain a correct behavior without sacrificing consistency, when a key expires, a DEL operation is synthesized in both the AOF file and gains all the attached replicas nodes. This way the expiration process is centralized in the master instance, and there is no chance of consistency errors.
为了获得一个正确的结果而不牺牲一致性,当一个key过期时,一个DEL操作会锁住AOF文件和能连接到的备份节点。过期进程集中在主节点上,并且不会出现一致性的错误。

However while the replicas connected to a master will not expire keys independently (but will wait for the DEL coming from the master), they’ll still take the full state of the expires existing in the dataset, so when a replica is elected to master it will be able to expire the keys independently, fully acting as a master.
然后当连接到主节点的备份(节点)不会立即过期(但是会等待来自于主节点的DEL来到),它们仍然会在数据集中以完整的过期状态存在,所以当备份(节点)被主节点选中时它就会立即将key过期,正如主节点中做的一样。

History
历史

  • Redis version >= 7.0.0: Added options: NX, XX, GT and LT.
    Redis版本大于7.0.0: 增加的操作:NX, XX, GT and LT.

注意,“从Redis2.6开始,过期时间的误差被限制在0-1毫秒之间。”指的是将key的状态从未过期转变为已过期之间的时间误差,并不包括将过期key删除。
过期key的删除是在附录中的被动和主动两种方式。

参考:
[1],Redis官方文档
[2],Redis中文文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值