Redis中如何设置过期时间

举报
林欣 发表于 2025/06/29 22:51:32 2025/06/29
【摘要】 在 Redis 中,可以通过多种命令为 Key 设置过期时间(TTL,Time To Live),过期后 Redis 会自动删除该 Key。以下是详细的设置方法、注意事项和最佳实践: 1. 设置过期时间的核心命令 (1) EXPIRE:为已存在的 Key 设置过期时间SET mykey "value" # 先设置一个 KeyEXPIRE mykey 60 # 设置...

在 Redis 中,可以通过多种命令为 Key 设置过期时间(TTL,Time To Live),过期后 Redis 会自动删除该 Key。以下是详细的设置方法、注意事项和最佳实践:


1. 设置过期时间的核心命令

(1) EXPIRE:为已存在的 Key 设置过期时间

SET mykey "value"       # 先设置一个 Key
EXPIRE mykey 60         # 设置 60 秒后过期
  • 返回值
    • 1:设置成功。
    • 0:Key 不存在或设置失败。

(2) EXPIREAT:设置 Key 在指定 Unix 时间戳过期

EXPIREAT mykey 1633046400  # 设置 Key 在 2021-10-01 00:00:00 过期
  • 适用场景:需要精确控制过期时间的场景(如定时任务)。

(3) SET 命令直接设置过期时间

SET mykey "value" EX 60      # 设置值并指定 60 秒后过期
SET mykey "value" PX 60000   # 设置值并指定 60000 毫秒后过期
  • 参数
    • EX <seconds>:秒级过期。
    • PX <milliseconds>:毫秒级过期。
  • 优点:原子操作,避免竞态条件。

(4) PERSIST:移除 Key 的过期时间

PERSIST mykey  # 将 Key 设置为永久有效

2. 检查和修改过期时间

(1) TTL:查看 Key 的剩余生存时间

TTL mykey  # 返回剩余秒数
# 返回值:
#   -2:Key 不存在。
#   -1:Key 存在但没有设置过期时间。
#   N:剩余 N 秒过期。

(2) PTTL:查看剩余毫秒数

PTTL mykey  # 返回剩余毫秒数

(3) 修改过期时间

  • 直接重新执行 EXPIREEXPIREAT 即可覆盖原有 TTL。

3. 批量设置过期时间

(1) 使用 MSET + EXPIRE(非原子)

MSET key1 "value1" key2 "value2"  # 批量设置值
EXPIRE key1 60
EXPIRE key2 120
  • 缺点:非原子操作,可能部分 Key 设置失败。

(2) 使用 Lua 脚本(原子操作)

-- 批量设置 Key 并指定不同 TTL
local keys = {"key1", "key2"}
local values = {"value1", "value2"}
local ttls = {60, 120}  --for i, key in ipairs(keys) do
    redis.call("SET", key, values[i], "EX", ttls[i])
end
  • 优点:保证所有操作原子性。

(3) 使用 SCAN + 管道(Pipeline)

# 伪代码:遍历匹配的 Key 并批量设置过期时间
SCAN 0 MATCH "user:*" COUNT 1000 | xargs -I {} redis-cli EXPIRE {} 3600
  • 适用场景:对已有 Key 批量补设过期时间。

4. 过期时间的底层实现

Redis 通过以下机制管理过期时间:

  1. 数据结构
    • 每个 Key 的元数据中存储 expire 字段(Unix 时间戳)。
    • 过期 Key 会被记录在全局的过期字典(expires 哈希表)中。
  2. 删除策略
    • 惰性删除:访问 Key 时检查是否过期。
    • 定期删除:后台线程随机抽查过期 Key 并删除。

5. 注意事项

(1) 过期时间的精度

  • Redis 的过期时间是秒级毫秒级(取决于命令)。
  • 实际删除可能存在 1 秒内 的延迟(受定期删除策略影响)。

(2) 持久化影响

  • RDB:生成快照时会过滤过期 Key,不会写入磁盘。
  • AOF:过期 Key 的删除操作会以 DEL 命令形式追加到 AOF 文件。

(3) 主从复制

  • 主库删除过期 Key 后会通知从库同步删除。
  • 如果主库未访问过期 Key,从库可能暂时保留(需依赖惰性删除)。

(4) 内存不足时的行为

  • 如果 Redis 内存达到 maxmemory 限制,会优先触发淘汰策略(如 LRU),而非等待过期删除。

6. 最佳实践

(1) 避免集中过期

  • 为批量 Key 设置随机 TTL,防止雪崩:
    -- Lua 脚本:为每个 Key 设置 60~120 秒的随机过期时间
    local key = KEYS[1]
    local value = ARGV[1]
    local ttl = 60 + math.random(60)  -- 60~120redis.call("SET", key, value, "EX", ttl)
    

(2) 热点数据谨慎设置过期时间

  • 对高频访问的 Key,建议:
    • 使用长 TTL(如数小时)。
    • 或通过后台任务定期刷新 TTL。

(3) 监控过期 Key

  • 启用过期事件通知:
    # redis.conf 中配置
    notify-keyspace-events Ex
    
  • 订阅频道:
    PSUBSCRIBE __keyevent@0__:expired  # 监听数据库 0 的过期事件
    

(4) 结合业务逻辑设计 TTL

  • 缓存场景:TTL 应略小于数据源的更新周期。
  • 会话管理:TTL 与用户会话时长一致(如 30 分钟)。

7. 常见问题

Q1:设置过期时间后,能否修改值而不影响 TTL?

  • 是的,SET 命令默认会保留原有 TTL:
    SET mykey "new_value"  # 保留原有 TTL
    
  • 如需重置 TTL,需重新执行 EXPIRE

Q2:为什么 TTL 返回 -2

  • 表示 Key 不存在(可能已被删除或未设置)。

Q3:如何设置永不过期的 Key?

  • 不设置过期时间,或使用 PERSIST 移除 TTL。

总结

命令 作用 示例
EXPIRE key seconds 设置 Key 在 N 秒后过期 EXPIRE mykey 60
EXPIREAT key timestamp 设置 Key 在 Unix 时间戳过期 EXPIREAT mykey 1633046400
SET key value EX seconds 原子性设置值和过期时间 SET mykey "value" EX 60
TTL key 查看剩余生存时间(秒) TTL mykey
PERSIST key 移除 Key 的过期时间 PERSIST mykey

通过合理使用这些命令,可以高效管理 Redis 中的数据生命周期,避免内存泄漏和性能问题。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。