NodeJS中ioredis设置缓存TTL异常:代码正常但redis-cli显示无过期时间
问题:ioredis设置带TTL的缓存后,redis-cli查询TTL返回-1
在Node.js应用中使用ioredis包时遇到异常:通过代码设置带TTL的缓存值后,client.ttl(key)能正常返回剩余过期时间,但用同端口连接的redis-cli执行TTL key却返回-1,且到期后键值对未被自动删除。
session-cache.js 代码
import Redis from 'ioredis'; const client = new Redis({ db: 0, host: 'localhost', port: 6379 }); export const cache = { async get(key) { const value = await client.get(key); return JSON.parse(value); }, async set(key, value, ttl) { if (ttl) { await client.set(key, value, "EX", ttl); // await client.expire(key, ttl) console.log(await client.ttl(key)); } else { await client.set(key, JSON.stringify(value)); } }, async delete(key) { await client.del(key); }, async ttl(key) { client.ttl(key, (err, result) => { if (err) { console.error(err); } else { console.log('TTL:', result); } }); } }
会话初始化代码
export async function initiateSessionCache(requestObject) { let sessionCache = await cache.get(requestObject.msisdn); // set initial session cache if session cache is falsy (session cache is empty) if (!sessionCache) { const initialState = { outerState: 'start', innerState: 'requestId', }; sessionCache = { state: initialState, requests: [], // create state stack to track user's state and allow user to go back to previous state stateStack: [initialState] }; await cache.set(requestObject.msisdn, sessionCache); } return sessionCache; }
排查方向及解决方法
1. 核心问题:数据序列化不一致
看你的set方法逻辑:当传入ttl参数时,直接将value存入Redis,没有做JSON.stringify序列化;但无ttl时却做了序列化。这会导致:
- 带TTL存入的对象会被Redis转为
[object Object]这类无效字符串 - 后续调用
cache.get时,JSON.parse解析无效字符串会返回null,触发initiateSessionCache里的重新设置逻辑——无TTL的set操作覆盖了带TTL的键,所以redis-cli查询TTL返回-1
修复方法:统一序列化逻辑,无论是否传入TTL,都将值转为JSON字符串:
async set(key, value, ttl) { const serializedValue = JSON.stringify(value); if (ttl) { await client.set(key, serializedValue, "EX", ttl); console.log(await client.ttl(key)); } else { await client.set(key, serializedValue); } }
2. Redis配置排查(次要)
如果上述修复后问题仍存在,检查Ubuntu系统的Redis配置:
- 确认redis.conf中未禁用过期键删除功能(默认开启,无需额外配置)
- 重启Redis服务确保配置生效:
sudo systemctl restart redis-server
3. 辅助验证步骤
- 调用
cache.set时,确认传入了有效的ttl数值(例如cache.set('test-key', {a:1}, 60)) - 在redis-cli中执行
KEYS *,确认键名和代码中使用的完全一致(注意大小写、特殊字符) - 用
client.keys('*')打印代码中识别的键,和redis-cli结果对比,排除键名不一致问题
内容的提问来源于stack exchange,提问作者FredylanGM
相关产品推荐
相关产品推荐

