ERM
redis
runtime_error
ai_generated
true
ERR Key expiry race condition: TTL updated but key already expired
ID: redis/key-expiry-race-condition
85%Fix Rate
80%Confidence
1Evidence
2023-11-10First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 6.0 | active | — | — | — |
| 7.0 | active | — | — | — |
| 7.2 | active | — | — | — |
Root Cause
A race condition occurred when multiple clients simultaneously update TTL and key value, causing the key to expire before the TTL update takes effect.
generic中文
多个客户端同时更新 TTL 和键值时发生竞态条件,导致键在 TTL 更新生效前已过期。
Official Documentation
https://redis.io/docs/latest/commands/expire/Workarounds
-
95% success Use EVAL with a script: 'local val = redis.call("GET", KEYS[1]); if val then redis.call("SET", KEYS[1], ARGV[1]); redis.call("EXPIRE", KEYS[1], ARGV[2]); return 1 else return 0 end'.
Use EVAL with a script: 'local val = redis.call("GET", KEYS[1]); if val then redis.call("SET", KEYS[1], ARGV[1]); redis.call("EXPIRE", KEYS[1], ARGV[2]); return 1 else return 0 end'. -
85% success Use WATCH on the key before GET, then MULTI/EXEC to update TTL. If WATCH triggers, retry.
Use WATCH on the key before GET, then MULTI/EXEC to update TTL. If WATCH triggers, retry.
中文步骤
使用 EVAL 执行脚本:'local val = redis.call("GET", KEYS[1]); if val then redis.call("SET", KEYS[1], ARGV[1]); redis.call("EXPIRE", KEYS[1], ARGV[2]); return 1 else return 0 end'。在 GET 前使用 WATCH 监视键,然后使用 MULTI/EXEC 更新 TTL。如果 WATCH 触发,则重试。
Dead Ends
Common approaches that don't work:
-
50% fail
SET with EX still has a race if key is deleted by another client before EXPIRE.
-
60% fail
Redis transactions are not atomic for conditional operations; EXPIRE may still fail if key expires during transaction.
-
75% fail
Race condition persists; repeated failures under high concurrency.