如何避免重复查询,高效从数据库向用户传递稳定数据?
优化方案:会话缓存+主动刷新,解决高频低变数据重复查询问题
这是个非常典型的高频低变数据优化场景,咱们可以通过会话缓存(Session)+ 数据更新时主动刷新缓存的组合方案来解决,既避免重复查询数据库,又能保证用户修改数据后能及时获取最新内容。
1. 用Session缓存用户基础数据
把用户的静态数据缓存到Session中,只有第一次访问、Session过期或者缓存被主动清除时,才去查询数据库。修改后的中间件代码如下:
router.use(function(req, res, next) { // 先检查Session里是否已有缓存的用户数据 if (req.session.userData) { // 把缓存数据挂载到req上,方便后续路由和EJS模板直接使用 req.userData = req.session.userData; return next(); } // 没有缓存时,再查询数据库 const uid = req.user.id; req.getConnection(function(err, conn) { if (err) { console.log(err); return next("Mysql error, check your query"); } // 注意:uid是唯一标识,查询结果取第一条即可 const query = conn.query('SELECT * FROM user_profile WHERE uid = ? ', uid, function(err, rows) { if (err) { console.log(err); return next(err, uid, "Mysql error, check your query"); } // 将查询到的用户数据存入Session缓存 req.session.userData = rows[0]; req.userData = req.session.userData; return next(); }); }); })
这样处理后,用户后续的导航操作都会直接读取Session里的缓存数据,不会每次都触发数据库查询,大幅降低数据库压力。
2. 在数据修改路由中主动刷新缓存
当用户修改姓名、用户名或企业信息时,执行完数据库更新操作后,必须同步更新Session里的缓存,避免出现“缓存与数据库数据不一致”的问题。示例代码如下:
router.post('/update-profile', function(req, res, next) { const uid = req.user.id; const updatedData = { name: req.body.name, username: req.body.username, company_info: req.body.company_info }; req.getConnection(function(err, conn) { if (err) return next(err); // 先更新数据库 conn.query('UPDATE user_profile SET ? WHERE uid = ?', [updatedData, uid], function(err, result) { if (err) return next(err); // 方案1:直接更新Session中的缓存(适合字段少的情况) req.session.userData = {...req.session.userData, ...updatedData}; // 方案2:删除缓存,让下一次请求自动重新查询(适合更新字段较多的场景) // delete req.session.userData; res.redirect('/profile'); }); }); });
3. 补充注意事项
- Session过期时间:可以根据业务需求设置合适的Session过期时间,比如1-2小时,用户长时间不操作后,Session会自动过期,下一次访问会重新查询最新数据。
- 多端修改场景:如果存在后台管理系统修改用户数据的情况,单纯依赖Session缓存可能会有延迟,这种情况可以考虑结合Redis等分布式缓存,或者在后台修改时主动触发用户缓存失效;但对于普通用户自行修改的场景,上面的方案完全够用。
- EJS模板兼容:因为我们把
userData挂载到了req对象上,EJS模板里可以直接用<%= req.userData.name %>、<%= req.userData.username %>来展示导航栏信息,和之前的使用方式完全兼容。
内容的提问来源于stack exchange,提问作者Cadmos
相关产品推荐
相关产品推荐

