Redis能否为列表单个元素设过期时间?附阅读记录场景需求与命令咨询
Hey there! Let's tackle your question about storing user reading records in Redis where each article ID in the list has its own expiration time (instead of the entire key expiring at once).
First off: Redis doesn't natively support setting expiration times for individual elements in a List (or Set, for that matter). The EXPIRE/PEXPIRE commands only work on top-level keys, not elements within a collection structure. So we need to use alternative data structures or patterns to achieve your goal.
Here are two practical, production-ready solutions:
Solution 1: Use a Sorted Set (ZSet)
This is the most efficient approach for most scenarios, as it combines storage, ordering, and expiration logic in one structure.
How it works:
- Use the user ID as the ZSet key (e.g.,
user:read:songkeyy). - Store each article ID as a member of the ZSet.
- Set the score of each member to the timestamp (in milliseconds) when the record should expire.
Example Commands:
Record a reading with expiration:
Suppose current timestamp is1698765432000(ms):# Article 1 expires in 100ms → score = 1698765432000 + 100 = 1698765432100 ZADD user:read:songkeyy 1698765432100 1 # Article 2 expires in 200ms → score = 1698765432000 + 200 = 1698765432200 ZADD user:read:songkeyy 1698765432200 2 # Article 3 expires in 30ms → score = 1698765432000 + 30 = 1698765432030 ZADD user:read:songkeyy 1698765432030 3Query valid (non-expired) reading records:
First, clean up expired entries (optional but recommended to avoid bloat), then fetch the remaining records:# Get current timestamp (replace with your actual current time in ms) CURRENT_TIMESTAMP=$(date +%s%3N) # Delete all entries where score (expiration time) is <= current time ZREMRANGEBYSCORE user:read:songkeyy 0 $CURRENT_TIMESTAMP # Fetch all valid article IDs ZRANGE user:read:songkeyy 0 -1
Pros & Cons:
- ✅ Efficient for both writes and reads
- ✅ Can easily add ordering (e.g., sort by expiration time or reading time)
- ❌ Requires managing timestamps manually
- ❌ Expired entries won't disappear automatically unless you run the cleanup command (you can trigger this on every read or via a periodic cron job)
Solution 2: Hash + Per-Article Expiration Keys
This approach is more intuitive if you prefer letting Redis handle expiration automatically, but it creates more keys.
How it works:
- Use a Hash to track all articles a user has read (user ID as the Hash key, article IDs as fields).
- Create a separate top-level key for each article read record, and set its expiration time directly with
PEXPIRE.
Example Commands:
Record a reading with expiration:
# Add article IDs to the user's Hash HSET user:read:songkeyy 1 1 HSET user:read:songkeyy 2 1 HSET user:read:songkeyy 3 1 # Set expiration for each individual article record (in milliseconds) PEXPIRE user:read:songkeyy:1 100 PEXPIRE user:read:songkeyy:2 200 PEXPIRE user:read:songkeyy:3 30Query valid reading records:
You'll need to check if each per-article key exists (since expired keys are automatically deleted by Redis):# Fetch all article IDs from the Hash ARTICLE_IDS=$(HKEYS user:read:songkeyy) # Filter out IDs where the corresponding expiration key no longer exists for ID in $ARTICLE_IDS; do if redis-cli EXISTS user:read:songkeyy:$ID; then echo $ID fi done(In application code, you'd loop through the Hash fields and run
EXISTSfor each.)
Pros & Cons:
- ✅ Redis automatically handles expiration (no manual timestamp management)
- ✅ Simple to understand
- ❌ Creates many additional keys (can bloat your Redis keyspace)
- ❌ Less efficient for large datasets (multiple
EXISTScalls add overhead)
Final Recommendation
If you're dealing with a large number of users or reading records, go with the Sorted Set approach—it's faster and more scalable. If you prioritize simplicity over raw performance, the Hash + per-key expiration pattern works perfectly.
内容的提问来源于stack exchange,提问作者Songkey

