无需重复查询即可将一致数据从数据库传递给用户的正确方法

Right way of passing consistent data from DB to user without repeatedly querying

数据库存储一些关于用户的数据,这些数据几乎永远不会改变。嗯,有时信息可能会改变,例如,如果用户想要编辑他的名字。

数据信息是关于每个用户的姓名、用户名及其公司数据。

当他需要创建发票时,前两个一直使用 ejs 显示在他的导航栏中,例如 User_1 is logged in,他的公司资料数据。

我目前的方法是使用 router.use 通过中间件获取用户数据,因此提取的信息始终可用于所有 routes/views,例如:

router.use(function(req, res ,next) { // this block of code is called as middleware in every route

    req.getConnection(function(err,conn){      
      uid = req.user.id;

       if(err){
          console.log(err);
          return next("Mysql error, check your query");
        }

        var 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");
          }

          var userData = rows;

          return next();
       });
    });
})

.

我知道这不是将用户配置文件数据传递给每个 route/view 的最佳方式,因为它会在用户每次浏览应用程序时进行新的数据库查询。

有什么更好的方法可以让这些数据可用而无需在每个路由中重复相同的查询一旦用户更改了部分数据就重新获取它们,喜欢他的全名吗?

您刚刚进入 "caching" 的世界,欢迎!对于这样的用例以及许多其他用例,缓存是一个非常受欢迎的选择。缓存本质上是存储数据的地方,您可以比进行完整的数据库查询或读取文件等更快地取回数据。

在我们继续之前,有必要考虑一下您的用例。如果您只为少数用户提供服务并且服务负载较低,则缓存可能会过度设计,实际上发出数据库请求可能是最简单的想法。随着事情的进展,添加缓存会给代码增加很多复杂性,这不足以吓到你,但足以导致难以追踪的错误。所以考虑一下你的服务负载,如果它不是很高(比如你工作的某个地方的内部应用程序可能每隔几分钟只处理几个请求)那么仅仅从数据库读取可能不会减慢请求太多.在这种情况下,从数据库读取是最简单且可能是最好的解决方案。但是,如果您注意到此数据库请求正在减慢您的请求应用程序或使其难以扩展,那么缓存可能适合您。

一个非常流行的方法是获取类似 "redis" 的东西,它是一个键值数据库,将所有内容保存在内存 (RAM) 中。 Redis 可以像 MySQL 一样作为服务使用,并且具有非常基本的查询语言。它速度快得令人眼花缭乱,并且可以扩展到巨大的负载。如果您使用的是 Express,则有许多 NPM 模块可以帮助您访问 redis 实例。只需输入您的凭据,然后您就可以发出 GET 和 SET 请求(获取数据或设置数据)。

在您的示例中,您可能希望以 JSON 格式针对用户 ID 或用户名在 Redis 中存储用户个人资料。然后,创建一个名为 getUserProfile 的函数,它接收 ID 或用户名。然后可以在 redis 中查找它,如果它找到记录然后它可以 return 它到你的主控制器逻辑。如果没有,它可以在你的 MySQL 数据库中查找它,将它保存在 redis 中,然后 return 它到控制器逻辑(这样它下次就可以从缓存中获取它).

你的下一个问题是计算机科学中一个非常棘手的问题。它是 "Cache Invalidation",在这种情况下,如果您的用户个人资料更新,您希望 "invalidate" 您的缓存。这样做的一种方法是在用户更新他们的个人资料(或保存的任何其他数据)时更新您的缓存版本。或者,您也可以只从 redis 中删除缓存版本,然后下次从 getUserProfile 请求它时,它将从 DB 中重新获取,然后放入 redis 以备下次使用。

还有许多其他方法可以解决此问题,但这很可能会以最简单的方式解决您的问题,而且不会产生太多开销。以后扩展起来也方便!