
Redis EXPIRETIME 命令詳細(xì)教程EXPIRETIME用于獲取 Key 的過期時(shí)間對(duì)應(yīng)的 Unix 時(shí)間戳秒。與TTL返回剩余秒數(shù)不同EXPIRETIME返回的是絕對(duì)時(shí)間點(diǎn)便于在應(yīng)用端直接判斷 Key 何時(shí)過期、進(jìn)行倒計(jì)時(shí)或與定時(shí)任務(wù)結(jié)合使用。本文基于 Redis 通用 Key 操作介紹EXPIRETIME。Redis 命令本身不區(qū)分大小寫因此EXPIRETIME、expiretime和Expiretime的效果相同文檔統(tǒng)一使用大寫形式。EXPIRETIME自 Redis 7.0 起可用。資料合集https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338一、命令概覽1. 基本語法EXPIRETIME key參數(shù)說明參數(shù)說明key要查詢過期時(shí)間戳的 Key返回值場(chǎng)景返回值Key 存在且有過期時(shí)間過期時(shí)間的 Unix 時(shí)間戳正整數(shù)秒Key 存在但無過期時(shí)間永久有效-1Key 不存在-22. 最簡單的示例先寫入一個(gè)值并設(shè)置過期時(shí)間再查看過期時(shí)間戳SET mykey Hello EX 3600 EXPIRETIME mykey返回類似(integer) 1724719123返回值是該 Key 過期時(shí)刻的 Unix 時(shí)間戳秒。用當(dāng)前時(shí)間戳減去它結(jié)果等于TTL的值。二、EXPIRETIME 的返回結(jié)果1. Key 存在且有過期時(shí)間SET session:user:1001 active EX 1800 EXPIRETIME session:user:1001返回一個(gè)正整數(shù)如(integer) 1724722723表示該 Key 將在該 Unix 時(shí)間戳對(duì)應(yīng)的時(shí)刻過期。2. Key 存在但無過期時(shí)間永久有效SET permanent-key forever EXPIRETIME permanent-key返回(integer) -1-1表示 Key 存在但沒有設(shè)置過期時(shí)間永遠(yuǎn)不會(huì)自動(dòng)過期。3. Key 不存在EXPIRETIME no-such-key返回(integer) -2-2表示 Key 不存在可能從未創(chuàng)建、已被刪除或已過期被清理。4. 已過期的 Key已經(jīng)過期但尚未被惰性/定期刪除清理的 KeyEXPIRETIME返回-2視為不存在SET temp-key value EX 1等待 1 秒后執(zhí)行EXPIRETIME temp-key返回(integer) -2Redis 在訪問時(shí)進(jìn)行惰性過期檢查因此即使 Key 尚在內(nèi)存中EXPIRETIME也會(huì)正確返回-2。5. 用絕對(duì)時(shí)間戳設(shè)置過期的 Key使用EXPIREAT或SET ... EXAT設(shè)置的 KeyEXPIRETIME返回的值就是設(shè)置時(shí)指定的時(shí)間戳SET promo:key summer-sale EXAT 1735689600 EXPIRETIME promo:key返回(integer) 1735689600用相對(duì)時(shí)間設(shè)置的 Key返回值也是絕對(duì)時(shí)間戳而非相對(duì)秒數(shù)SET cache:key value EX 3600 EXPIRETIME cache:key返回的是當(dāng)前時(shí)間 3600 秒對(duì)應(yīng)的絕對(duì)時(shí)間戳。三、EXPIRETIME 與 TTL 的關(guān)系EXPIRETIME返回過期時(shí)刻的絕對(duì)時(shí)間戳TTL返回剩余生存秒數(shù)。兩者存在數(shù)學(xué)關(guān)系TTL(key) EXPIRETIME(key) - 當(dāng)前Unix時(shí)間戳1. 對(duì)比示例SET mykey value EX 3600 TTL mykey EXPIRETIME mykey TIME返回類似TTL mykey - (integer) 3600 EXPIRETIME mykey - (integer) 1724722723 TIME - 1) 1724719123 2) 456789驗(yàn)證1724722723 - 1724719123 3600與TTL返回值一致。2. 何時(shí)使用 EXPIRETIME何時(shí)使用 TTL需求推薦命令原因判斷 Key 是否快過期TTL直接得到剩余秒數(shù)顯示倒計(jì)時(shí)TTL剩余秒數(shù)可直接用于倒計(jì)時(shí)獲取 Key 何時(shí)過期絕對(duì)時(shí)間EXPIRETIME返回絕對(duì)時(shí)間戳與外部定時(shí)任務(wù)結(jié)合EXPIRETIME絕對(duì)時(shí)間便于跨系統(tǒng)對(duì)齊判斷 Key 是永久還是臨時(shí)TTL或EXPIRETIME均可返回-1即永久四、EXPIRETIME 與相關(guān)命令的區(qū)別1. EXPIRETIME 與 PEXPIRETIMEEXPIRETIME返回秒級(jí)時(shí)間戳PEXPIRETIME返回毫秒級(jí)時(shí)間戳SET mykey value PEX 3600000 EXPIRETIME mykey # 返回秒級(jí)時(shí)間戳如 1724722723 PEXPIRETIME mykey # 返回毫秒級(jí)時(shí)間戳如 1724722723456命令精度返回值示例EXPIRETIME key秒1724722723PEXPIRETIME key毫秒1724722723456需要毫秒精度時(shí)使用PEXPIRETIME。2. EXPIRETIME 與 TTL / PTTL命令返回內(nèi)容單位EXPIRETIME key過期時(shí)刻的絕對(duì)時(shí)間戳秒PEXPIRETIME key過期時(shí)刻的絕對(duì)時(shí)間戳毫秒TTL key剩余生存時(shí)間秒PTTL key剩余生存時(shí)間毫秒SET mykey value EX 3600 EXPIRETIME mykey # 過期時(shí)間戳 TTL mykey # 剩余秒數(shù) PTTL mykey # 剩余毫秒數(shù) PEXPIRETIME mykey # 過期毫秒時(shí)間戳3. EXPIRETIME 與 EXPIREAT / EXPIRE 的區(qū)別EXPIREAT和EXPIRE是寫命令用于設(shè)置過期時(shí)間EXPIRETIME是只讀命令用于查詢過期時(shí)間戳。命令操作類型作用EXPIREAT key timestamp寫設(shè)置絕對(duì)過期時(shí)間EXPIRE key seconds寫設(shè)置相對(duì)過期時(shí)間EXPIRETIME key只讀查詢過期時(shí)間戳4. 返回值對(duì)比總表狀態(tài)EXPIRETIMETTLPTTLPEXPIRETIMEKey 存在且有過期過期秒級(jí)時(shí)間戳剩余秒數(shù)剩余毫秒數(shù)過期毫秒級(jí)時(shí)間戳Key 存在無過期-1-1-1-1Key 不存在-2-2-2-2五、EXPIRETIME 與不同數(shù)據(jù)類型EXPIRETIME作用于整個(gè) Key所有數(shù)據(jù)類型String、Hash、List、Set、Sorted Set、Stream 等的行為一致。HSET user:1001 name Alice age 30 EXPIRE user:1001 3600 EXPIRETIME user:1001RPUSH queue:jobs job-a job-b EXPIRE queue:jobs 1800 EXPIRETIME queue:jobsSADD tags redis python EXPIRE tags 7200 EXPIRETIME tags返回值都是 Key 的過期時(shí)間戳與數(shù)據(jù)類型無關(guān)。六、過期時(shí)間的刷新與 EXPIRETIME1. 覆蓋式更新后的反映對(duì)已有過期時(shí)間的 Key 再次執(zhí)行EXPIRE或EXPIREATEXPIRETIME返回的值會(huì)更新為新的過期時(shí)間戳SET mykey value EX 3600 EXPIRETIME mykey # 返回 timestamp1 EXPIREAT mykey 1767225600 EXPIRETIME mykey # 返回 17672256002. SET 會(huì)清除過期時(shí)間使用SET命令覆蓋 Key 的值時(shí)不帶EX/PX/EXAT/PXAT過期時(shí)間被清除EXPIRETIME返回-1SET mykey old EX 3600 EXPIRETIME mykey # 返回正數(shù) SET mykey new EXPIRETIME mykey # 返回 -13. PERSIST 后的反映PERSIST移除過期時(shí)間后EXPIRETIME返回-1SET mykey value EX 3600 PERSIST mykey EXPIRETIME mykey # 返回 -14. 各命令對(duì) EXPIRETIME 結(jié)果的影響操作EXPIRETIME 返回值變化EXPIRE key seconds更新為新的過期時(shí)間戳EXPIREAT key timestamp更新為指定的時(shí)間戳PEXPIRE key ms更新為新的過期時(shí)間戳PEXPIREAT key timestamp更新為指定的時(shí)間戳SET key value無選項(xiàng)變?yōu)?1清除過期SET key value EX seconds更新為新的過期時(shí)間戳SET key value EXAT timestamp更新為指定的時(shí)間戳PERSIST key變?yōu)?1移除過期INCR/LPUSH/HSET等不影響保持原值GETEX key取決于參數(shù)可修改或清除過期時(shí)間七、事務(wù)、Pipeline 與并發(fā)場(chǎng)景1. 在事務(wù)中使用EXPIRETIME可以放入事務(wù)隊(duì)列MULTI SET mykey value EX 3600 EXPIRETIME mykey TTL mykey EXECEXEC執(zhí)行后返回各命令的結(jié)果。2. 只讀特性與并發(fā)安全EXPIRETIME是只讀命令不修改任何數(shù)據(jù)不會(huì)影響其他客戶端的操作。多個(gè)客戶端同時(shí)調(diào)用EXPIRETIME是安全的。3. 并發(fā)場(chǎng)景下的注意事項(xiàng)由于EXPIRETIME返回的是查詢時(shí)刻的過期時(shí)間戳如果在兩次查詢之間有其他客戶端修改了 Key 的過期時(shí)間如EXPIRE、SET、PERSIST返回值可能不同。這屬于正常的并發(fā)行為先查再判斷的多步流程不是原子操作。需要原子地檢查過期時(shí)間并執(zhí)行操作時(shí)使用 Lua 腳本localexpireredis.call(EXPIRETIME,KEYS[1])ifexpire0thenreturnexpireelsereturnredis.call(EXPIRE,KEYS[1],ARGV[1])end4. Pipeline 批量查詢需要查詢大量 Key 的過期時(shí)間戳?xí)r可以使用 Pipeline 批量發(fā)送EXPIRETIME命令減少網(wǎng)絡(luò)往返。八、在常見客戶端中的使用方式1. redis-cliredis-cli SET mykeyvalueEX3600redis-cli EXPIRETIME mykey redis-cli SET permanentforeverredis-cli EXPIRETIME permanent redis-cli EXPIRETIME no-such-key分別返回正數(shù)時(shí)間戳、-1、-2。2. Pythonredis-pyimportredis clientredis.Redis(hostlocalhost,port6379,decode_responsesTrue)client.set(mykey,value,ex3600)# 獲取過期時(shí)間戳expire_timeclient.expiretime(mykey)print(expire_time)# 如 1724722723# 永久 Keyclient.set(permanent,forever)print(client.expiretime(permanent))# -1# 不存在的 Keyprint(client.expiretime(no-such-key))# -23. Node.jsnode-redisimport{createClient}fromredis;constclientcreateClient();awaitclient.connect();awaitclient.set(mykey,value,{EX:3600});constexpireTimeawaitclient.expireTime(mykey);console.log(expireTime);// 如 1724722723awaitclient.set(permanent,forever);console.log(awaitclient.expireTime(permanent));// -1console.log(awaitclient.expireTime(no-such-key));// -2awaitclient.quit();4. JavaJedistry(JedisjedisnewJedis(localhost,6379)){jedis.set(mykey,value,SetParams.setParams().ex(3600));// 獲取過期時(shí)間戳longexpireTimejedis.expireTime(mykey);System.out.println(expireTime);// 如 1724722723// 永久 Keyjedis.set(permanent,forever);System.out.println(jedis.expireTime(permanent));// -1// 不存在的 KeySystem.out.println(jedis.expireTime(no-such-key));// -2}九、典型使用場(chǎng)景1. 倒計(jì)時(shí)顯示獲取 Key 的絕對(duì)過期時(shí)間戳在客戶端計(jì)算剩余時(shí)間并顯示倒計(jì)時(shí)SET flash-sale:product active EX 3600 EXPIRETIME flash-sale:product客戶端用EXPIRETIME返回的時(shí)間戳減去當(dāng)前時(shí)間戳得到剩余秒數(shù)并顯示。2. 過期時(shí)間對(duì)齊多個(gè) Key 需要在同一時(shí)刻過期時(shí)用EXPIRETIME確認(rèn)是否已對(duì)齊EXPIRETIME cache:a EXPIRETIME cache:b EXPIRETIME cache:c如果返回值不同用EXPIREAT統(tǒng)一調(diào)整EXPIREAT cache:a 1735689600 EXPIREAT cache:b 1735689600 EXPIREAT cache:c 17356896003. 監(jiān)控與告警監(jiān)控系統(tǒng)查詢 Key 的過期時(shí)間戳判斷是否即將過期并提前告警EXPIRETIME session:critical如果返回的時(shí)間戳接近當(dāng)前時(shí)間戳觸發(fā)告警提醒續(xù)期。4. 與外部定時(shí)任務(wù)結(jié)合應(yīng)用端獲取 Key 的過期時(shí)間戳后在對(duì)應(yīng)時(shí)刻注冊(cè)定時(shí)任務(wù)處理過期事件EXPIRETIME task:cleanup5. 數(shù)據(jù)生命周期審計(jì)定期掃描設(shè)置了過期時(shí)間的 Key審計(jì)過期時(shí)間是否合理SCAN 0 EXPIRETIME key1 EXPIRETIME key2十、性能與使用建議時(shí)間復(fù)雜度O(1)。EXPIRETIME是只讀命令A(yù)CL 類別為keyspace、read、fast不會(huì)修改數(shù)據(jù)不會(huì)觸發(fā)通知。性能優(yōu)異頻繁調(diào)用不會(huì)對(duì) Redis 造成壓力。只需判斷 Key 是否存在時(shí)用EXISTS語義更清晰需要過期時(shí)間信息時(shí)用EXPIRETIME。需要剩余秒數(shù)時(shí)用TTL需要絕對(duì)時(shí)間戳?xí)r用EXPIRETIME兩者可互相換算。EXPIRETIME對(duì)永久 Key 返回-1、對(duì)不存在的 Key 返回-2與TTL的返回值約定一致便于統(tǒng)一處理。集群模式下EXPIRETIME作用于單個(gè) Key不受哈希槽限制。Redis 7.0 以下版本不支持EXPIRETIME調(diào)用會(huì)返回錯(cuò)誤。低版本場(chǎng)景可用TTL加上當(dāng)前時(shí)間戳間接計(jì)算。十一、常見問題排查問題 1EXPIRETIME 返回 -2 但 Key 應(yīng)該存在按以下順序檢查是否連接到了正確的 Redis 實(shí)例、端口和邏輯數(shù)據(jù)庫不同SELECT庫中 Key 相互獨(dú)立。Key 是否已經(jīng)過期用TTL確認(rèn)返回-2表示不存在。Key 名稱是否包含不可見字符、前后空格或大小寫差異。Key 是否被其他客戶端刪除或覆蓋SET不帶選項(xiàng)會(huì)清除過期時(shí)間但 Key 仍存在如果返回-2則 Key 本身不存在。EXISTS mykey TTL mykey TYPE mykey問題 2EXPIRETIME 返回 -1 但預(yù)期有過期時(shí)間可能的原因在設(shè)置過期時(shí)間后執(zhí)行了SET不帶EX/EXAT等選項(xiàng)覆蓋了 Key 的值導(dǎo)致過期時(shí)間被清除。執(zhí)行了PERSIST命令移除了過期時(shí)間。查詢的 Key 與設(shè)置過期的 Key 不是同一個(gè)名稱差異。問題 3EXPIRETIME 返回的時(shí)間戳與預(yù)期不符可能的原因使用了EXPIRE相對(duì)秒數(shù)而非EXPIREAT絕對(duì)時(shí)間戳設(shè)置過期返回的時(shí)間戳是設(shè)置時(shí)刻 相對(duì)秒數(shù)。過期時(shí)間被其他客戶端用EXPIRE、EXPIREAT或SET ... EX更新過。時(shí)區(qū)理解錯(cuò)誤返回的是 UTC Unix 時(shí)間戳不是本地時(shí)間。問題 4Redis 7.0 以下版本報(bào)錯(cuò)EXPIRETIME從 Redis 7.0 開始支持。低版本調(diào)用會(huì)返回錯(cuò)誤ERR unknown command EXPIRETIME替代方案使用TTL key獲取剩余秒數(shù)加上當(dāng)前時(shí)間戳得到過期時(shí)間戳redis-cli TTL mykey# 獲取剩余秒數(shù)redis-cli TIME# 獲取當(dāng)前時(shí)間戳# 過期時(shí)間戳 當(dāng)前時(shí)間戳 TTL問題 5EXPIRETIME 與 PEXPIRETIME 返回值不一致EXPIRETIME返回秒級(jí)時(shí)間戳PEXPIRETIME返回毫秒級(jí)時(shí)間戳。兩者數(shù)值相差約 1000 倍但表示的是同一過期時(shí)刻EXPIRETIME mykey # 如 1724722723 PEXPIRETIME mykey # 如 1724722723456PEXPIRETIME EXPIRETIME * 1000 毫秒部分。十二、完整練習(xí)下面的示例演示從設(shè)置過期時(shí)間、查詢過期時(shí)間戳、對(duì)比 TTL 與 EXPIRETIME、驗(yàn)證不同狀態(tài)返回值到與SET、PERSIST、EXPIREAT等命令配合使用的完整流程DEL demo:key DEL demo:perm DEL demo:short # 基本用法設(shè)置相對(duì)過期查詢絕對(duì)時(shí)間戳 SET demo:key hello EX 3600 EXPIRETIME demo:key TTL demo:key TIME # 驗(yàn)證關(guān)系EXPIRETIME 當(dāng)前時(shí)間戳 TTL # 如 EXPIRETIME1724722723, TIME1724719123, TTL3600 # 永久 Key 返回 -1 SET demo:perm forever EXPIRETIME demo:perm TTL demo:perm # 不存在的 Key 返回 -2 EXPIRETIME demo:noexist TTL demo:noexist # 用絕對(duì)時(shí)間戳設(shè)置過期 EXPIREAT demo:key 1767225600 EXPIRETIME demo:key # SET 清除過期時(shí)間 SET demo:key new value EXPIRETIME demo:key # SET ... EXAT 設(shè)置過期時(shí)間戳 SET demo:key with ttl EXAT 1735689600 EXPIRETIME demo:key # PERSIST 后返回 -1 PERSIST demo:key EXPIRETIME demo:key # 過期后返回 -2 SET demo:short gone EX 1 # 等待 1 秒后執(zhí)行 # EXPIRETIME demo:short # TTL demo:short # 對(duì)比 EXPIRETIME 與 PEXPIRETIME SET demo:precision value EX 3600 EXPIRETIME demo:precision PEXPIRETIME demo:precision預(yù)期結(jié)果EXPIRETIME demo:key返回正數(shù)時(shí)間戳TTL demo:key返回約3600EXPIRETIME - TIME約等于TTL。EXPIRETIME demo:perm返回-1TTL demo:perm返回-1。EXPIRETIME demo:noexist返回-2TTL demo:noexist返回-2。EXPIREAT demo:key 1767225600后EXPIRETIME demo:key返回1767225600。SET demo:key new value后EXPIRETIME demo:key返回-1。SET demo:key with ttl EXAT 1735689600后EXPIRETIME demo:key返回1735689600。PERSIST demo:key后EXPIRETIME demo:key返回-1。過期后EXPIRETIME demo:short返回-2。EXPIRETIME與PEXPIRETIME返回值相差約 1000 倍表示同一過期時(shí)刻。十三、命令速查表需求命令返回值類型獲取過期時(shí)間戳秒EXPIRETIME key秒級(jí) Unix 時(shí)間戳獲取過期時(shí)間戳毫秒PEXPIRETIME key毫秒級(jí) Unix 時(shí)間戳獲取剩余生存時(shí)間秒TTL key剩余秒數(shù)獲取剩余生存時(shí)間毫秒PTTL key剩余毫秒數(shù)判斷 Key 是否存在EXISTS key0 或 1獲取 Key 的數(shù)據(jù)類型TYPE key類型字符串設(shè)置秒級(jí)過期時(shí)間EXPIRE key seconds0 或 1設(shè)置絕對(duì)過期時(shí)間秒EXPIREAT key timestamp0 或 1設(shè)置毫秒級(jí)過期時(shí)間PEXPIRE key ms0 或 1設(shè)置絕對(duì)過期時(shí)間毫秒PEXPIREAT key timestamp0 或 1原子設(shè)置值和過期時(shí)間戳SET key value EXAT timestampOK移除過期時(shí)間PERSIST key0 或 1獲取服務(wù)器當(dāng)前時(shí)間TIME秒 微秒總結(jié)EXPIRETIME的核心作用是返回 Key 過期時(shí)刻的 Unix 時(shí)間戳秒便于應(yīng)用端獲取絕對(duì)過期時(shí)間點(diǎn)EXPIRETIME key使用時(shí)重點(diǎn)注意四點(diǎn)返回值約定與TTL一致正數(shù)表示過期時(shí)間戳-1表示永久有效-2表示 Key 不存在。EXPIRETIME返回的是絕對(duì)時(shí)間戳TTL返回的是剩余秒數(shù)兩者可互相換算。SET不帶選項(xiàng)會(huì)清除過期時(shí)間EXPIRE/EXPIREAT會(huì)更新過期時(shí)間PERSIST會(huì)移除過期時(shí)間EXPIRETIME能反映這些變化。EXPIRETIME從 Redis 7.0 開始支持低版本可用TTL加當(dāng)前時(shí)間戳間接計(jì)算過期時(shí)間戳。