Redis中Key过期时间的设置与应用方式
作者:没事学AI
一、设置Key过期时间的命令
(一)EXPIRE命令
EXPIRE用于设置一个Key在指定秒数后过期。其语法为:EXPIRE key seconds 。
比如,我们要将名为user:1:session的Key设置为3600秒(1小时)后过期,在Redis客户端中执行:
127.0.0.1:6379> EXPIRE user:1:session 3600 (integer) 1
返回值1表示设置成功,如果Key不存在或设置失败则返回0 。此命令适用于对时间精度要求不高,以秒为单位设置过期时间的场景,像一般的缓存数据失效时间设置。
(二)PEXPIRE命令
PEXPIRE与EXPIRE类似,不过它是以毫秒为单位设置Key的过期时间,语法为:PEXPIRE key milliseconds 。
若要将message:1这个Key设置为5000毫秒(5秒)后过期,操作如下:
127.0.0.1:6379> PEXPIRE message:1 5000 (integer) 1
该命令适用于对时间精度要求较高的场景,例如某些对消息时效性要求严格的消息队列场景。
(三)EXPIREAT命令
EXPIREAT通过指定一个Unix时间戳(以秒为单位),让Key在该时间点过期。语法为:EXPIREAT key timestamp 。
假设我们获取到当前时间戳为1693382400(对应2023年9月1日00:00:00),要让cache:data这个Key在2023年9月2日00:00:00过期,即时间戳1693468800,则执行:
127.0.0.1:6379> EXPIREAT cache:data 1693468800 (integer) 1
这种方式适用于需要在特定时间点让Key失效的场景,如限时活动相关数据的过期控制。
(四)PEXPIREAT命令
PEXPIREAT同样是基于时间戳设置过期时间,但时间戳是以毫秒为单位,语法为:PEXPIREAT key milliseconds - timestamp 。
比如要让token:user1在2023年9月1日00:00:01.500过期,对应的毫秒时间戳为1693382401500,操作如下:
127.0.0.1:6379> PEXPIREAT token:user1 1693382401500 (integer) 1
适用于对过期时间点精度要求极高的场景,如金融交易中某些临时凭证的过期时间设置。
二、在设置值时同时设置过期时间
(一)SET命令结合EX参数
使用SET key value EX seconds可以在设置Key值的同时指定其在多少秒后过期。
例如,设置product:1:price的值为99.9,并让它在86400秒(1天)后过期:
127.0.0.1:6379> SET product:1:price 99.9 EX 86400 OK
这种方式在需要创建新的缓存数据并设置过期时间时非常便捷,代码更简洁。
(二)SET命令结合PX参数
SET key value PX milliseconds用于在设置Key值时指定毫秒级别的过期时间。
比如设置tmp:data的值为some temp data,并在3000毫秒(3秒)后过期:
127.0.0.1:6379> SET tmp:data "some temp data" PX 3000 OK
适用于对时间精度要求高且在设置值时就确定过期时间的场景。
(三)SETEX命令
SETEX key seconds value专门用于设置一个带有过期时间(秒为单位)的字符串值。
如设置news:1:content的值为一篇新闻内容,并让它在7200秒(2小时)后过期:
127.0.0.1:6379> SETEX news:1:content "This is a news" 7200 OK
在只针对字符串类型的Key设置值和过期时间时,SETEX命令更为直观。
三、获取Key的剩余过期时间
(一)TTL命令
TTL用于获取一个Key的剩余过期时间(以秒为单位)。语法为:TTL key 。
对于之前设置的user:1:session,可以这样获取其剩余过期时间:
127.0.0.1:6379> TTL user:1:session (integer) 3590
返回值3590表示该Key还有3590秒过期。如果Key不存在或已过期,返回-2;如果Key没有设置过期时间(即永久有效),返回-1 。此命令常用于检查缓存数据何时失效,以便提前进行数据更新等操作。
(二)PTTL命令
PTTL获取Key的剩余过期时间(以毫秒为单位),语法为:PTTL key 。
对于设置了毫秒级过期时间的message:1,获取剩余过期时间操作如下:
127.0.0.1:6379> PTTL message:1 (integer) 4990
返回值4990表示还有4990毫秒过期。同样,Key不存在或已过期返回-2,永久有效返回-1 。适用于需要精确了解剩余毫秒级过期时间的场景。
四、移除Key的过期时间
使用PERSIST命令可以移除一个Key的过期时间,使其变为永久有效。语法为:PERSIST key 。
例如,之前设置了过期时间的cache:data,若要让它永久有效,执行:
127.0.0.1:6379> PERSIST cache:data (integer) 1
返回值1表示操作成功,之后再使用TTL cache:data查询,会返回-1,表示该Key已变为永久有效。在某些情况下,原本设置了过期时间的Key,由于业务需求变更,需要长期保存时,就可使用PERSIST命令。
五、应用场景及案例
(一)缓存场景
在Web应用中,常使用Redis作为缓存来提升数据读取速度。例如,电商网站中商品详情数据的缓存。
假设我们有一个商品详情页面,每次查询数据库获取商品详情数据开销较大。可以将商品详情数据缓存到Redis中,并设置合理的过期时间。
import redis
r = redis.Redis(host='localhost', port=6379, db=0)
def get_product_detail(product_id):
product_key = f'product:{product_id}:detail'
product_detail = r.get(product_key)
if product_detail is None:
# 从数据库获取商品详情数据
product_detail = get_product_detail_from_db(product_id)
if product_detail:
# 将数据缓存到Redis,设置1小时过期
r.setex(product_key, 3600, product_detail)
return product_detail
这里使用SETEX命令在设置商品详情数据时,同时设置了1小时的过期时间。当缓存过期后,下次请求会重新从数据库获取数据并更新缓存,保证数据的实时性。
(二)会话管理场景
在Web应用的用户会话管理中,Redis可用于存储用户会话信息。
例如,用户登录成功后,将用户的会话信息存储在Redis中,并设置过期时间,以自动清理长时间未活动的会话。
import redis
import uuid
r = redis.Redis(host='localhost', port=6379, db=0)
def create_session(user_id):
session_id = str(uuid.uuid4())
session_key = f'session:{session_id}'
session_data = {'user_id': user_id}
# 将会话信息存储到Redis,设置30分钟过期
r.setex(session_key, 1800, str(session_data))
return session_id
def get_session(session_id):
session_key = f'session:{session_id}'
session_data = r.get(session_key)
if session_data:
return eval(session_data.decode('utf - 8'))
return None
上述代码中,CREATE_SESSION函数创建用户会话时,使用SETEX设置会话信息在30分钟后过期。GET_SESSION函数用于获取会话信息,若会话已过期,GET操作返回None,提示用户重新登录。
(三)分布式锁场景
在分布式系统中,使用Redis实现分布式锁时,设置Key的过期时间可防止死锁。
import redis
import time
r = redis.Redis(host='localhost', port=6379, db=0)
def acquire_lock(lock_key, expire_time=10):
lock_value = str(uuid.uuid4())
success = r.set(lock_key, lock_value, ex=expire_time, nx=True)
return success, lock_value
def release_lock(lock_key, lock_value):
pipe = r.pipeline()
while True:
try:
pipe.watch(lock_key)
if pipe.get(lock_key).decode('utf - 8') == lock_value:
pipe.multi()
pipe.delete(lock_key)
pipe.execute()
return True
pipe.unwatch()
break
except redis.WatchError:
continue
return False
在ACQUIRE_LOCK函数中,使用SET命令结合EX参数设置锁的过期时间为10秒。如果持有锁的进程在10秒内未完成操作并释放锁,Redis会自动删除锁Key,防止其他进程永远无法获取锁,即避免死锁。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
