Redis

关注公众号 jb51net

关闭
首页 > 数据库 > Redis > Redis中Key过期时间设置与应用

Redis中Key过期时间的设置与应用方式

作者:没事学AI

文章主要介绍了Redis中设置和管理Key过期时间的多种命令,包括EXPIRE、PEXPIRE、EXPIREAT、PEXPIREAT、SET命令结合EX或PX参数、SETEX命令,以及获取剩余过期时间的TTL和PTTL命令,最后通过缓存、会话管理和分布式锁等应用场景展示了这些命令的实际应用

一、设置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,防止其他进程永远无法获取锁,即避免死锁。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文