61人参与 • 2026-08-28 • Redis
expireat 用于为 key 设置以 unix 时间戳(秒)为单位的绝对过期时间,到期后 redis 会自动删除该 key。与 expire 设置相对时间(从现在起多少秒后过期)不同,expireat 指定的是一个绝对时间点,适用于需要在特定日期或时刻让 key 失效的场景。
本文基于 redis 通用 key 操作介绍 expireat。redis 命令本身不区分大小写,因此 expireat、expireat 和 expireat 的效果相同;文档统一使用大写形式。expireat 自 redis 1.2 起可用,条件选项 nx、xx、gt、lt 从 redis 7.0 开始支持。
expireat key timestamp [nx | xx | gt | lt]
参数说明:
| 参数 | 说明 |
|---|---|
| key | 要设置过期时间的 key |
| timestamp | unix 时间戳(秒),绝对过期时间点 |
| nx | 仅当 key 没有过期时间时才设置(not exists),redis 7.0+ |
| xx | 仅当 key 已有过期时间时才设置(exists),redis 7.0+ |
| gt | 仅当新过期时间戳大于当前过期时间戳时才设置(greater than),redis 7.0+ |
| lt | 仅当新过期时间戳小于当前过期时间戳时才设置(less than),redis 7.0+ |
返回值:
先写入一个字符串值,然后设置在指定 unix 时间戳过期:
set mykey "hello" expireat mykey 1735689600
返回:
(integer) 1
查看剩余生存时间:
ttl mykey
返回值为当前时间到 1735689600 的剩余秒数(正数)。
查看过期时间戳:
expiretime mykey
返回:
(integer) 1735689600
unix 时间戳是从 utc 1970 年 1 月 1 日 00:00:00 起经过的秒数。expireat 接受的就是这种秒级 unix 时间戳。
常见时间点的 unix 时间戳(示例):
| 时间(utc) | unix 时间戳 |
|---|---|
| 2025-01-01 00:00:00 | 1735689600 |
| 2025-06-01 00:00:00 | 1748736000 |
| 2026-01-01 00:00:00 | 1767225600 |
| 2026-08-28 00:00:00 | 1787548800 |
在 redis-cli 中可以用 time 命令获取服务器当前时间:
time
返回类似:
1) "1724719123" 2) "456789"
第一个值为秒级时间戳,第二个值为微秒部分。
在 shell 中获取:
date +%s
可以结合 shell 命令计算未来的时间戳。例如设置 1 小时后过期:
redis-cli expireat mykey $(( $(date +%s) + 3600 ))
设置明天同一时间过期:
redis-cli expireat mykey $(( $(date +%s) + 86400 ))
set promo:coupon:1001 "discount50" expireat promo:coupon:1001 1767225600
返回 (integer) 1,该 key 将在 utc 2026-01-01 00:00:00 过期。
expireat no-such-key 1735689600
返回:
(integer) 0
key 不存在时,expireat 返回 0,不会创建 key。
传入的时间戳小于当前时间戳时,key 会立即过期(相当于被删除):
set temp "value" expireat temp 1 exists temp
exists temp 返回 (integer) 0。
利用这一特性可以实现"立即删除"的效果,但通常应使用 del 或 unlink。
unix 时间戳 0 对应 1970-01-01 00:00:00 utc,显然在过去,key 会立即过期:
set temp "value" expireat temp 0 exists temp
exists temp 返回 (integer) 0。
传入负值时间戳时,key 也会立即过期:
set temp "value" expireat temp -1 exists temp
exists temp 返回 (integer) 0。
redis 7.0 及以上版本支持条件选项,用于更精细地控制过期时间的设置行为。
nx(not exists):只有当 key 当前没有关联过期时间(即永久有效)时,才设置新的过期时间。
set permanent-key "forever" expireat permanent-key 1735689600 nx
返回 (integer) 1,因为该 key 原本没有过期时间。
如果 key 已有过期时间:
set temp-key "temp" ex 60 expireat temp-key 1735689600 nx
返回 (integer) 0,因为 nx 条件不满足。
xx(exists):只有当 key 当前已有过期时间时,才更新为新的过期时间。
set temp-key "temp" ex 60 expireat temp-key 1735689600 xx
返回 (integer) 1,因为该 key 已有过期时间,成功更新。
如果 key 是永久有效的:
set permanent-key "forever" expireat permanent-key 1735689600 xx
返回 (integer) 0,因为 xx 条件不满足。
gt(greater than):只有当新的过期时间戳大于当前剩余过期时间戳时,才更新过期时间。redis 7.0+ 支持。
set mykey "value" ex 100 expireat mykey 1735689600 gt
如果 1735689600 对应的过期时间在当前过期时间之后,返回 (integer) 1,过期时间被延长。
如果新过期时间更早:
set mykey "value" exat 1735689600 expireat mykey 1000 gt
时间戳 1000 对应 1970-01-01,远在当前过期时间之前,返回 (integer) 0。
lt(less than):只有当新的过期时间戳小于当前剩余过期时间戳时,才更新过期时间。redis 7.0+ 支持。
set mykey "value" exat 1735689600 expireat mykey 1735660000 lt
如果 1735660000 < 1735689600,返回 (integer) 1,过期时间被缩短。
如果新过期时间更晚:
set mykey "value" ex 100 expireat mykey 1735689600 lt
如果 1735689600 对应的过期时间在当前过期时间之后,返回 (integer) 0。
nx 与 xx 互斥,gt 与 lt 互斥。gt 和 lt 不能与 nx 同时使用(没有当前过期时间时无法比较大小)。
expireat 设置绝对过期时间(unix 时间戳),expire 设置相对过期时间(从现在起的秒数):
expire key 3600 # 3600 秒后过期 expireat key 1735689600 # 在指定 unix 时间戳过期
两者可以互相转换:expireat key timestamp 等价于 expire key (timestamp - 当前时间戳)。
需要在特定时间点过期时用 expireat,需要"多少秒后"过期时用 expire。
expireat 接受秒级时间戳,pexpireat 接受毫秒级时间戳:
expireat key 1735689600 # 秒级时间戳 pexpireat key 1735689600000 # 毫秒级时间戳
两者语义相同,精度不同。需要毫秒级精度时使用 pexpireat。
set 命令(redis 6.2+)可以通过 exat 选项在设置值的同时指定绝对过期时间戳,是原子操作:
set cache:key "value" exat 1735689600
等效于(但更高效且原子):
set cache:key "value" expireat cache:key 1735689600
推荐优先使用 set ... exat 形式,避免 set 成功但 expireat 失败导致 key 永久有效的风险。
expiretime 返回 key 过期时间对应的 unix 时间戳(秒),redis 7.0+ 支持:
set mykey "value" exat 1735689600 expiretime mykey
返回:
(integer) 1735689600
| 状态 | expiretime 返回值 |
|---|---|
| key 存在且有过期时间 | 过期时间戳(正数) |
| key 存在但无过期时间 | -1 |
| key 不存在 | -2 |
persist 用于移除 key 的过期时间,使其变为永久有效:
set temp-key "value" exat 1735689600 persist temp-key ttl temp-key
ttl temp-key 返回 -1(永久有效)。
| 命令 | 时间类型 | 精度 | 说明 |
|---|---|---|---|
| expire key seconds | 相对 | 秒 | 多少秒后过期 |
| pexpire key ms | 相对 | 毫秒 | 多少毫秒后过期 |
| expireat key timestamp | 绝对 | 秒 | 在指定时间戳过期 |
| pexpireat key timestamp | 绝对 | 毫秒 | 在指定毫秒时间戳过期 |
| ttl key | — | 秒 | 剩余秒数 |
| pttl key | — | 毫秒 | 剩余毫秒数 |
| expiretime key | — | 秒 | 过期时间戳(秒) |
| pexpiretime key | — | 毫秒 | 过期时间戳(毫秒) |
| persist key | — | — | 移除过期时间 |
对已有过期时间的 key 再次执行 expireat,会覆盖原有的过期时间:
set mykey "value" exat 1735689600 expireat mykey 1767225600 expiretime mykey
expiretime mykey 返回 1767225600,过期时间被重置。
使用 set 命令覆盖 key 的值时(不带 exat/pxat/ex/px 选项),原有的过期时间会被清除,key 变为永久有效:
set mykey "old" exat 1735689600 set mykey "new" ttl mykey
ttl mykey 返回 -1。
| 命令 | 对过期时间的影响 |
|---|---|
| set、getset | 清除过期时间(key 变为永久有效) |
| set ... exat / pxat | 设置新的绝对过期时间 |
| set ... ex / px | 设置新的相对过期时间 |
| incr / decr / incrby | 保留原有过期时间 |
| lpush / rpush | 保留原有过期时间 |
| hset / hmset | 保留原有过期时间 |
| sadd / zadd | 保留原有过期时间 |
| rename | 源 key 的过期时间转移到目标 key |
| copy | 默认不复制过期时间 |
| persist | 移除过期时间 |
| getex | 可同时修改过期属性 |
当客户端访问某个 key 时,redis 会检查该 key 是否已过期,如果已过期则立即删除并返回不存在。
特点:
redis 会周期性地(默认每秒 10 次)随机抽取一部分设置了过期时间的 key 进行检查,删除已过期的 key。
特点:
expireat 作用于整个 key,所有数据类型(string、hash、list、set、sorted set、stream 等)的过期行为一致。
hset user:1001 name "alice" age 30 expireat user:1001 1735689600
rpush queue:jobs job-a job-b job-c expireat queue:jobs 1735689600
sadd tags redis python java expireat tags 1735689600
zadd leaderboard 100 "player1" 200 "player2" expireat leaderboard 1735689600
过期后整个 key 及其所有数据都会被删除。
expireat 可以放入事务队列:
multi set promo:banner "summer-sale" expireat promo:banner 1735689600 exec
exec 执行后返回各命令的结果。
“先 set 再 expireat” 不是原子操作。如果 set 成功后客户端崩溃或网络中断,expireat 可能不会执行,导致 key 永久有效。
推荐使用原子的 set ... exat 形式(redis 6.2+):
set promo:banner "summer-sale" exat 1735689600
使用 expireat 续期分布式锁时,应使用 xx 选项确保锁仍然存在:
expireat lock:resource 1735689600 xx
如果返回 0,说明锁已经不存在(可能已过期或被释放)。
需要为大量 key 设置同一过期时间点时,可以使用 pipeline 批量发送 expireat 命令,减少网络往返。
redis-cli set promo:key "summer-sale" redis-cli expireat promo:key 1735689600 redis-cli expiretime promo.key
结合 shell 动态计算时间戳:
# 设置明天同一时间过期 redis-cli expireat mykey $(( $(date +%s) + 86400 )) # 设置 2025-06-01 00:00:00 utc 过期 redis-cli expireat mykey $(date -d "2025-06-01 00:00:00 utc" +%s)
import redis
import time
client = redis.redis(host="localhost", port=6379, decode_responses=true)
client.set("promo:key", "summer-sale")
# 设置在指定 unix 时间戳过期
expire_at = int(time.time()) + 3600 # 1 小时后
client.expireat("promo:key", expire_at)
# 使用 datetime 对象(redis-py 支持)
from datetime import datetime, timezone, timedelta
expire_dt = datetime(2025, 6, 1, 0, 0, 0, tzinfo=timezone.utc)
client.expireat("promo:key", expire_dt)
# 查看过期时间戳
expire_time = client.expiretime("promo:key")
print(expire_time)
import { createclient } from "redis";
const client = createclient();
await client.connect();
await client.set("promo:key", "summer-sale");
// 设置在指定 unix 时间戳过期
const expireat = math.floor(date.now() / 1000) + 3600; // 1 小时后
await client.expireat("promo:key", expireat);
// 查看过期时间戳
const expiretime = await client.expiretime("promo:key");
console.log(expiretime);
await client.quit();import java.time.instant;
import redis.clients.jedis.jedis;
try (jedis jedis = new jedis("localhost", 6379)) {
jedis.set("promo:key", "summer-sale");
// 设置在指定 unix 时间戳过期
long expireat = instant.now().getepochsecond() + 3600; // 1 小时后
long result = jedis.expireat("promo:key", expireat);
system.out.println(result); // 1
// 使用 date 对象
import java.util.date;
jedis.expireat("promo:key", date.from(instant.parse("2025-06-01t00:00:00z")));
// 查看过期时间戳
long expiretime = jedis.expiretime("promo:key");
system.out.println(expiretime);
}
促销活动在指定日期结束,自动清理相关 key:
set promo:summer:2025 "active" expireat promo:summer:2025 1751328000 # 2025-07-01 00:00:00 utc
活动到期后 key 自动失效,无需手动清理。
利用 key 过期事件(keyspace notification)在指定时间触发任务:
set task:send-email:1001 "data" exat 1735689600
配合 notify-keyspace-events ex 配置,订阅过期事件来触发定时任务。
验证码在特定时间点失效:
# 设置验证码在当天 23:59:59 过期 redis-cli set sms:code:13800138000 "123456" redis-cli expireat sms:code:13800138000 $(date -d "today 23:59:59" +%s)
用户会话在当天结束时间点自动失效:
redis-cli set session:abc123 "user:1001" redis-cli expireat session:abc123 $(date -d "tomorrow 00:00:00" +%s)
秒杀活动在特定时刻开始或结束:
set seckill:stock "100" expireat seckill:stock 1735689600 # 活动结束时间
日志或统计数据在指定日期后自动清理:
set log:2025-01:access "count_data" expireat log:2025-01:access 1767225600 # 2026-01-01 自动清理 2025 年 1 月数据
可能的原因:
time expiretime mykey ttl mykey
可能的原因:
可能的原因:
expireat 接受秒级时间戳,pexpireat 接受毫秒级时间戳。如果误将毫秒时间戳传给 expireat,会导致过期时间远超预期(大约 1000 倍)。
# 错误:传入了毫秒时间戳 expireat key 1735689600000 # 实际过期时间约为 56670 年后 # 正确:秒级时间戳 expireat key 1735689600 # 如果需要毫秒精度,使用 pexpireat pexpireat key 1735689600000
从节点不会主动过期 key,而是等待主节点的 del 命令。如果从节点读取到"应该已过期"的 key,这是正常行为。确保读取策略与业务需求匹配。
下面的示例演示从设置绝对过期时间、验证 ttl 和 expiretime、条件选项、更新过期时间,到与 set ... exat、persist 等命令配合使用的完整流程:
del demo:key del demo:perm del demo:renew # 获取当前时间 time # 基本用法:设置绝对过期时间 set demo:key "hello" expireat demo:key 1767225600 expiretime demo:key ttl demo:key # 对不存在的 key 设置过期 expireat demo:noexist 1767225600 # set 会清除过期时间 set demo:key "new value" ttl demo:key # 使用 set ... exat 原子设置 set demo:key "with ttl" exat 1767225600 expiretime demo:key # persist 移除过期时间 persist demo:key ttl demo:key # 条件选项示例(需要 redis 7.0+) # nx:仅当无过期时间时设置 set demo:perm "permanent" expireat demo:perm 1767225600 nx expiretime demo:perm expireat demo:perm 1735689600 nx # 返回 0,因为已有过期时间 # xx:仅当有过期时间时更新 expireat demo:perm 1735689600 xx expiretime demo:perm # 续期场景模拟 set demo:renew "session" exat 1735689600 expiretime demo:renew expireat demo:renew 1767225600 xx # 续期到更晚的时间 expiretime demo:renew # hash 类型的过期 hset demo:hash name "alice" age 30 expireat demo:hash 1767225600 expiretime demo:hash # 验证过去时间戳立即过期 set demo:past "gone" expireat demo:past 1 exists demo:past
预期结果:
| 需求 | 命令 | 时间类型 | 精度 |
|---|---|---|---|
| 在指定 unix 时间戳过期(秒) | expireat key timestamp | 绝对 | 秒 |
| 在指定 unix 时间戳过期(毫秒) | pexpireat key timestamp | 绝对 | 毫秒 |
| 多少秒后过期 | expire key seconds | 相对 | 秒 |
| 多少毫秒后过期 | pexpire key ms | 相对 | 毫秒 |
| 原子设置值和绝对过期时间 | set key value exat timestamp | 绝对 | 秒 |
| 原子设置值和绝对过期时间 | set key value pxat timestamp | 绝对 | 毫秒 |
| 获取剩余生存时间(秒) | ttl key | — | 秒 |
| 获取剩余生存时间(毫秒) | pttl key | — | 毫秒 |
| 获取过期时间戳(秒) | expiretime key | — | 秒 |
| 获取过期时间戳(毫秒) | pexpiretime key | — | 毫秒 |
| 移除过期时间 | persist key | — | — |
| 仅当无过期时间时设置 | expireat key timestamp nx | 绝对 | 秒 |
| 仅当有过期时间时更新 | expireat key timestamp xx | 绝对 | 秒 |
| 仅当新过期时间更晚时设置 | expireat key timestamp gt | 绝对 | 秒 |
| 仅当新过期时间更早时设置 | expireat key timestamp lt | 绝对 | 秒 |
expireat 的核心作用是为 key 设置以秒级 unix 时间戳为单位的绝对过期时间,到期后 redis 自动删除该 key:
expireat key timestamp [nx | xx | gt | lt]
使用时重点注意五点:
到此这篇关于redis中expireat命令实现的文章就介绍到这了,更多相关redis expireat命令内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论