EXPIRE、PEXPIRE:设置生存时间
用户可以通过执行EXPIRE命令或者PEXPIRE命令为键设置一个生存时间(Time To Live,TTL):键的生存时间在设置之后就会随着时间的流逝而不断地减少,当一个键的生存时间被消耗殆尽时,Redis就会移除这个键。
Redis提供了EXPIRE命令用于设置秒级精度的生存时间,它可以让键在指定的秒数之后自动被移除:
EXPIRE key seconds
而PEXPIRE命令则用于设置毫秒级精度的生存时间,它可以让键在指定的毫秒数之后自动被移除:
PEXPIRE key milliseconds
EXPIRE命令和PEXPIRE命令在生存时间设置成功时返回1;如果用户给定的键并不存在,那么命令返回0表示设置失败。
以下是一个使用EXPIRE命令的例子:
redis> SET msg "hello world"
OK
redis> EXPIRE msg 5
(integer) 1
redis> GET msg -- 在5s之内访问,键存在
"hello world"
redis> GET msg -- 在5s之后访问,键不再存在
(nil)
上面的代码通过执行EXPIRE命令为msg键设置了5s的生存时间:
-
如果我们在5s之内访问msg键,那么Redis将返回msg键的值"hello world"。
-
如果我们在5s之后访问msg键,那么Redis将返回一个空值,因为msg 键已经自动被移除了。
表12-1展示了msg键从设置生存时间到被移除的整个过程。

以下则是一个使用PEXPIRE命令的例子:
redis> SET number 10086
OK
redis> PEXPIRE number 6500
(integer) 1
redis> GET number -- 在6500ms(即6.5s)之内访问,键存在
"10086"
redis> GET number -- 在6500ms之后访问,键不再存在
(nil)
表12-2展示了number键从设置生存时间到被移除的整个过程。

更新键的生存时间
当用户对一个已经带有生存时间的键执行EXPIRE命令或PEXPIRE命令时,键原有的生存时间将会被移除,并设置新的生存时间。
举个例子,如果我们执行以下命令,将msg键的生存时间设置为10s:
redis> EXPIRE msg 10
(integer) 1
然后在10s之内执行以下命令:
redis> EXPIRE msg 50
(integer) 1
那么msg键的生存时间将被更新为50s,并重新开始倒数,表12-3展示了这个更新过程。

其他信息
-
复杂度:EXPIRE命令和PEXPIRE命令的复杂度都为O(1)。
-
版本要求:EXPIRE命令从Redis 1.0.0版本开始可用,PEXPIRE命令从 Redis 2.6.0版本开始可用。
示例:带有自动移除特性的缓存程序
用户在使用缓存程序的时候,必须考虑缓存的时效性:对于内容不断变换的应用来说,一份缓存存在的时间越长,它与实际内容之间的差异往往也就越大,因此为了让缓存能够及时地反映真实的内容,程序必须定期对缓存进行更新。
第2章曾展示过如何使用字符串键构建缓存程序,但那个缓存程序有一个明显的缺陷,那就是它无法自动移除过时的缓存。如果我们真的要在实际中使用那个程序,就必须再编写一个辅助程序来定期地删除旧缓存,这样一来使用缓存将会变得非常麻烦。
幸运的是,通过使用Redis的键过期功能,我们可以为缓存程序加上自动移除特性,并通过这个特性自动移除过期的、无效的缓存。
代码清单12-1展示了一个能够为缓存设置最大有效时间的缓存程序,这个程序与第2章展示的缓存程序的绝大部分代码都是相同的,主要区别在于,新程序除了会把指定的内容缓存起来之外,还会使用 EXPIRE 命令为缓存设置生存时间,从而使缓存可以在指定时间到达之后自动被移除。
class VolatileCache:
def __init__(self, client):
self.client = client
def set(self, key, value, timeout):
"""
把数据缓存到键 key 里面,并为其设置过期时间。
如果键 key 已经有值,那么使用新值去覆盖旧值。
"""
self.client.set(key, value)
self.client.expire(key, timeout)
def get(self, key):
"""
获取键 key 储存的缓存数据。
如果键不存在,又或者缓存已经过期,那么返回 None 。
"""
return self.client.get(key)
以下代码简单地展示了这个缓存程序的使用方法:
>>> from redis import Redis
>>> from unsafe_volatile_cache import VolatileCache
>>> client = Redis(decode_responses=True)
>>> cache = VolatileCache(client)
>>> cache.set("homepage", "<html><p>hello world</p></html>", 10) # 设置缓存
>>> cache.get("homepage") # 这个缓存在10s之内有效
'<html><p>hello world</p></html>'
>>> cache.get("homepage") # 10s过后,缓存自动被移除
>>>