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

Next.js 15如何配置Redis自定义缓存?@neshca工具兼容问题求助

解决方案:自定义Next.js 15缓存处理器实现Redis+LRU降级

由于@neshca/cache-handler暂未适配Next.js 15的缓存API变更,我们可以通过自定义缓存处理器实现需求,以下是完整落地方案:

1. 依赖准备

安装核心依赖包:

npm install redis lru-cache
# 或 yarn add redis lru-cache

2. 实现自定义缓存处理器

在项目根目录的app文件夹下创建cache-handler.ts,实现Redis+LRU自动降级逻辑:

import { createClient } from 'redis';
import LRU from 'lru-cache';
import type { CacheHandler } from 'next/dist/server/web/spec-extension/cache-handler';

// 初始化Redis客户端
const redisClient = createClient({
  url: process.env.REDIS_URL || 'redis://localhost:6379',
});

// 标记Redis可用性,连接失败时自动切换到LRU
let redisAvailable = true;
redisClient.on('error', () => (redisAvailable = false));
redisClient.connect().catch(() => (redisAvailable = false));

// 初始化LRU本地缓存,可根据业务调整配置
const lruCache = new LRU({
  max: 1000, // 最大缓存条目数
  ttl: 60 * 60 * 1000, // 默认1小时过期
});

const cacheHandler: CacheHandler = {
  // 获取缓存
  async get(key: string) {
    try {
      if (redisAvailable) {
        const value = await redisClient.get(key);
        if (value) return JSON.parse(value);
      }
      return lruCache.get(key);
    } catch {
      redisAvailable = false;
      return lruCache.get(key);
    }
  },

  // 设置缓存
  async set(key: string, value: any, options?: { tags?: string[]; ttl?: number }) {
    const ttlSec = options?.ttl || 3600;
    const ttlMs = ttlSec * 1000;

    try {
      if (redisAvailable) {
        await redisClient.set(key, JSON.stringify(value), { EX: ttlSec });
        // 维护标签与缓存键的映射,支持revalidateTag
        if (options?.tags?.length) {
          for (const tag of options.tags) {
            await redisClient.sAdd(`tag:${tag}`, key);
          }
        }
      }
      lruCache.set(key, value, { ttl: ttlMs });
    } catch {
      redisAvailable = false;
      lruCache.set(key, value, { ttl: ttlMs });
    }
  },

  // 删除缓存
  async delete(key: string) {
    try {
      if (redisAvailable) await redisClient.del(key);
      lruCache.delete(key);
    } catch {
      redisAvailable = false;
      lruCache.delete(key);
    }
  },

  // 按标签失效缓存
  async revalidateTag(tag: string) {
    try {
      if (redisAvailable) {
        const keys = await redisClient.sMembers(`tag:${tag}`);
        if (keys.length) {
          await redisClient.del(...keys);
          await redisClient.del(`tag:${tag}`);
        }
      }
      // LRU按标签清理:需提前在缓存值中携带tags字段,或维护本地标签映射
      for (const [key] of lruCache.entries()) {
        const cachedValue = lruCache.get(key);
        if (cachedValue?.tags?.includes(tag)) {
          lruCache.delete(key);
        }
      }
    } catch {
      redisAvailable = false;
      // 同上处理LRU的标签清理
      for (const [key] of lruCache.entries()) {
        const cachedValue = lruCache.get(key);
        if (cachedValue?.tags?.includes(tag)) {
          lruCache.delete(key);
        }
      }
    }
  },
};

export default cacheHandler;

3. 配置Next.js启用自定义处理器

修改next.config.ts,指定缓存处理器路径:

import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  experimental: {
    cacheHandler: './app/cache-handler.ts',
  },
};

export default nextConfig;

4. 兼容App目录与服务器组件

在App目录的服务器组件中,直接使用Next.js原生缓存API即可,缓存操作会自动路由到Redis或LRU:

// app/page.tsx 服务器组件示例
import { unstable_cache } from 'next/cache';

// 封装带缓存的请求
const fetchCachedData = unstable_cache(
  async () => {
    const res = await fetch('https://api.example.com/data', { cache: 'force-cache' });
    return res.json();
  },
  ['data-cache-key'], // 缓存键
  { tags: ['data-tag'], ttl: 3600 } // 标签与过期时间
);

export default async function Page() {
  const data = await fetchCachedData();
  return <div>{JSON.stringify(data)}</div>;
}

关键注意事项

  • Redis容错:通过监听客户端错误事件,自动切换到LRU,避免服务因Redis不可用崩溃。
  • LRU配置优化:根据业务场景调整max(内存占用)和ttl(缓存时效)参数。
  • 标签清理性能:如果需要高频使用revalidateTag,建议在LRU中也维护标签-键的映射表,避免遍历所有缓存条目。
  • 类型安全:确保缓存值的JSON序列化/反序列化逻辑正确,避免类型错误。

内容的提问来源于stack exchange,提问作者Besok

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:25:54