You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 00:21:26