Redis 的 hash 类型本身不支持直接为单个字段设置过期时间。过期时间(TTL)只能针对整个 hash 键设置,而不能针对其中的某个字段单独设置。

原因

Redis 的过期机制是基于键的,而不是基于字段的。当为一个键设置过期时间时,整个键(包括其所有字段)会在过期时间到达后被删除。

解决方案

如果需要为 hash 中的某个字段实现类似过期的功能,可以考虑以下方法:

使用外部数据结构

  • 可以为每个需要过期的字段单独存储一个键,并设置过期时间。例如:

    HSET user:1000 name "Alice"
    SET user:1000:name:expire "Alice" EX 60  # 设置 name 字段的过期时间为 60 秒
  • 在读取时,先检查该字段的过期键是否存在:

    GET user:1000:name:expire

    如果返回 nil,说明该字段已过期。

使用 Lua 脚本

  • 可以通过 Lua 脚本在 Redis 中实现复杂的逻辑,例如检查字段的过期时间并删除过期的字段。例如:

    local field = ARGV[1]
    local expireKey = KEYS[1] .. ":" .. field .. ":expire"
    if redis.call("EXISTS", expireKey) == 0 then
        redis.call("HDEL", KEYS[1], field)
    end
    return redis.call("HGET", KEYS[1], field)

    调用方式:

    EVAL "lua_script_above" 1 user:1000 name

使用 Sorted Set 实现字段过期

  • 可以将 hash 字段和过期时间存储在 Sorted Set 中,利用分数(score)表示过期时间戳。例如:

    ZADD user:1000:expire 1672502400 name  # 设置 name 字段的过期时间为 2023-01-01
  • 在读取时,先检查当前时间是否大于字段的过期时间戳:

    ZRANGEBYSCORE user:1000:expire -inf 1672502400

使用 Redis Modules

  • 如果需要更复杂的功能,可以使用 Redis Modules(如 RedisGears 或 RediSearch)来实现自定义的过期逻辑。