Next.js服务端node-cache跨API无法共享缓存问题求助
Next.js中node-cache跨API路由无法共享缓存的解决方法
问题原因
你遇到的问题本质是node-cache属于内存级缓存,在Next.js的运行环境中无法跨请求或跨实例共享,具体分两种场景:
- 开发模式:Next.js的热重载机制会在代码变动时重新加载模块,每次请求可能生成新的Cache实例,导致缓存无法持久化。
- 生产Serverless模式:如果部署在Vercel、Netlify这类Serverless平台,每个API请求可能被分配到不同的函数实例,每个实例有独立的内存空间,缓存无法跨实例共享。
另外可以先快速排查:API1存入的URL键和API2查询的URL是否完全一致(比如大小写、末尾斜杠、参数编码等细节),不过从你日志里API2的Cache.keys()为空来看,大概率是实例不共享的问题。
解决方案
方案一:用单例模式确保Cache实例唯一(解决开发模式问题)
修改你的cache.ts,改用单例模式创建Cache,避免热重载时重复创建实例:
import NodeCache from 'node-cache'; let cacheInstance: NodeCache | undefined; export default function getCache() { if (!cacheInstance) { cacheInstance = new NodeCache({ stdTTL: 60 * 60 * 6 }); // 6小时 } return cacheInstance; }
然后在API1和API2中这样使用:
// API1中 import getCache from '@/utils/cache'; const Cache = getCache(); // API2中同理 import getCache from '@/utils/cache'; const Cache = getCache();
方案二:改用外部缓存服务(解决生产Serverless场景)
如果是生产环境的Serverless部署,内存缓存根本无法跨实例共享,必须用外部缓存服务,比如Redis、Vercel KV等。这里以Redis为例:
- 安装依赖:
npm install redis
- 创建新的
cache.ts:
import { createClient } from 'redis'; // 从环境变量读取Redis连接地址 const redisClient = createClient({ url: process.env.REDIS_URL }); // 连接Redis,捕获错误 redisClient.connect().catch(err => console.error('Redis连接失败:', err)); // 获取缓存 export async function getCachedValue<T>(key: string): Promise<T | null> { try { const value = await redisClient.get(key); return value ? JSON.parse(value) : null; } catch (err) { console.error('获取缓存失败:', err); return null; } } // 设置缓存(带过期时间) export async function setCachedValue<T>(key: string, value: T): Promise<void> { try { await redisClient.setEx(key, 60 * 60 * 6, JSON.stringify(value)); } catch (err) { console.error('设置缓存失败:', err); } }
- 在API1和API2中使用:
// API1中 import { getCachedValue, setCachedValue } from '@/utils/cache'; async function fetchFromUrl(url: string): Promise<UrlContent | null> { const cachedContent = await getCachedValue<UrlContent>(url); if (cachedContent) { return cachedContent; } // ... 你的计算逻辑 ... await setCachedValue(url, cleanedContent); return cleanedContent; }
额外检查项
确认API1存入的URL和API2查询的URL完全一致:
- 有没有大小写差异(比如
https://Example.com和https://example.com是不同的键) - 末尾是否有斜杠(比如
/api/data和/api/data/) - URL参数的顺序是否一致(比如
?a=1&b=2和?b=2&a=1)
内容的提问来源于stack exchange,提问作者Chuang Fu
相关产品推荐
相关产品推荐

