为Server Actions实现缓存:可行性及实现方法问询
为Server Actions实现缓存的几种方案
当然可以给Server Actions实现缓存,针对你的getProjects函数,这里有几种实用的方案:
1. 内存级缓存(适合单服务器/开发环境)
这种方案最简单,用内存存储缓存数据,适合单实例场景,缺点是服务器重启或多实例部署时缓存会失效:
"use server" // 内存缓存容器,单实例内有效 const cacheStore = new Map(); export const getProjects = async () => { const cacheKey = "projects_list"; const cachedEntry = cacheStore.get(cacheKey); // 检查缓存是否在1小时有效期内 if (cachedEntry && Date.now() - cachedEntry.timestamp < 3600 * 1000) { return cachedEntry.data; } // 缓存失效,执行数据库查询 const projects = await db( ` SELECT p.id, p.project_name, (SELECT i.image_url FROM images i WHERE i.project_id = p.id ORDER BY i.id DESC LIMIT 1) AS latest_image FROM projects p ` ); // 更新缓存,记录时间戳 cacheStore.set(cacheKey, { data: projects, timestamp: Date.now() }); return projects; };
2. 外部缓存系统(适合生产多实例环境)
用Redis这类分布式缓存系统,解决多实例缓存不一致的问题,生产环境首选:
"use server" import Redis from 'ioredis'; // 初始化Redis客户端,从环境变量读取连接地址 const redisClient = new Redis(process.env.REDIS_URL); export const getProjects = async () => { const cacheKey = "projects_list"; const cachedData = await redisClient.get(cacheKey); if (cachedData) { // 解析缓存的JSON数据 return JSON.parse(cachedData); } const projects = await db( ` SELECT p.id, p.project_name, (SELECT i.image_url FROM images i WHERE i.project_id = p.id ORDER BY i.id DESC LIMIT 1) AS latest_image FROM projects p ` ); // 设置缓存1小时过期 await redisClient.set(cacheKey, JSON.stringify(projects), 'EX', 3600); return projects; };
3. Next.js专属:unstable_cache API(Next.js 13+)
如果你用的是Next.js,官方提供了unstable_cache可以直接给Server Actions添加缓存,无需自己管理存储:
"use server" import { unstable_cache } from 'next/cache'; // 封装原始查询函数 const fetchProjects = async () => { return await db( ` SELECT p.id, p.project_name, (SELECT i.image_url FROM images i WHERE i.project_id = p.id ORDER BY i.id DESC LIMIT 1) AS latest_image FROM projects p ` ); }; // 用unstable_cache包装,设置1小时重新验证时间 export const getProjects = unstable_cache( fetchProjects, ['projects_list'], // 用于区分缓存的唯一标识数组 { revalidate: 3600 } // 缓存有效期(秒) );
注意:
unstable_cache目前是不稳定API,后续版本可能有变更,使用时留意Next.js官方文档更新。
额外注意事项
- 确保缓存键唯一,避免和其他业务的缓存数据冲突
- 当项目数据更新时,需要主动清除对应缓存(比如调用
redisClient.del(cacheKey)或Next.js的revalidateTag),避免返回旧数据 - 内存缓存不要存储过大的数据,防止服务器内存溢出
内容的提问来源于stack exchange,提问作者Morgana Freeman
相关产品推荐
相关产品推荐

