Node.js Express应用node-cache无法实时更新的问题排查
Node.js Express中node-cache缓存无法实时更新的问题排查
我在Node.js Express应用里用node-cache时遇到了缓存不实时更新的问题:初始缓存有3个任务,创建新任务后调用「get all」接口还是返回3个;重启应用后缓存才更新,能返回4个任务。我查了不少资料但没找到原因,想知道缓存是否应该实时更新,以及我哪里操作错了?
相关代码
创建任务接口
@Post('create') @Middleware(new RateLimiter(manyRequest).getMiddleware()) async create( req: Request, res: Response ) { const createTask = new CreateTask(new PrismaManageRepository()); const userId = req.context.userId._id try { const { task } = await createTask.execute({ ...req.body, ...{ userId: userId }, }); this.cache.del(this.taskCacheKey); // 我也试过这么写: this.cache.set(this.taskCacheKey, task, (60 * 60 * 24)); return { task: res.status(201).json(TaskViewModel.toHTTP(task)) }; } catch (err) { return this.errorResponse(res, err as Error); }
获取所有任务接口
@Get("all") @Middleware(new RateLimiter(fewRequest + 2).getMiddleware()) getAllTasks = async ( req: Request, res: Response ) => { const cachedTasks = this.cache.get(this.taskCacheKey); if (cachedTasks) { return res.status(200).json(cachedTasks); } const queryAllTasks = new QueryAllTasks(new PrismaTaskQueryRepository()); const userId = req.context.userId._id; try { const { tasks } = await queryAllTasks.execute(userId); const tasksData = tasks.map(TaskViewModel.toHTTP); this.cache.set(this.taskCacheKey, tasksData); return res.status(200).json(tasksData); } catch (err) { return logger.error(err); } };
问题分析与解决方案
核心错误
你在创建任务时的缓存更新逻辑完全错误:
getAllTasks接口缓存的是任务数组,但你在create接口里删除缓存后,手动存入的是单个新任务。这会导致后续调用「get all」时,直接返回缓存里的单个任务,而不是触发数据库查询获取完整列表。- 重启应用后缓存被清空,「get all」接口会重新查询数据库,自然能拿到包含新任务的完整列表。
正确的缓存实时更新方式
缓存必须实时更新,才能让用户操作后立即看到最新数据。你有两种可选方案:
删除缓存,让查询接口自动重建(推荐)
只保留删除缓存的逻辑,去掉手动存入单个任务的代码:// create接口中修改为 this.cache.del(this.taskCacheKey); // 删掉this.cache.set(...)这一行下一次调用「get all」时,缓存已被清除,接口会自动从数据库拉取所有任务(包括新创建的),再重新存入缓存。
手动更新缓存数组
如果不想让下一次请求触发数据库查询,可以先获取当前缓存的任务数组,把新任务转换为统一格式后加入数组,再重新存入缓存:// create接口中 const currentCachedTasks = this.cache.get(this.taskCacheKey) || []; const newTaskHTTP = TaskViewModel.toHTTP(task); this.cache.set(this.taskCacheKey, [...currentCachedTasks, newTaskHTTP], 60 * 60 * 24);注意必须保证新任务的格式和
getAllTasks中存入的格式完全一致(都经过TaskViewModel.toHTTP处理)。
内容的提问来源于stack exchange,提问作者Lucas V Marangoni
相关产品推荐
相关产品推荐

