当前位置: 首页 > 面试题库 >

如何在Redis中将MongoDB文档存储为缓存并按超时刷新

晏卓君
2023-03-14
问题内容

我有处理嵌套JSON文档的nodejs应用程序,如下所示:

var post = {
  id: 123,
  title: 'Sterling Archer',    
  comments: [
    {text: 'Comment text', tags: ['tag1', 'tag2', 'tag3']},
    {text: 'Comment test', tags: ['tag2', 'tag5']}
  ]  
};

并将它们存储在MongoDB数据库中。我的文档需要经常更新,但是如您所知,由于其性质,MongoDB的写入速度非常慢。为了解决此问题,我决定将文档存储在Redis中,并在某个超时时间(例如1-2小时后)刷新到MongoDB。

因此,这里是我的更新方法的代码示例:

var redis_cli = require("redis").createClient();

app.post('/update/:id', function (req, res, next) {

  var id = req.params.id
  redis_cli.get(id, function (err, document) {
      if (err) return next(err);

      // If there is no key, try to get from MongoDB
      if (!document) {
         DocumentModel.findOneByid(id, function (err, document) {
             if (err) return next(err);
             if (!document) return next(new Error("Document with id " + id + " does not exists"));

             // Document in MongoDB, so store in redis
             redis_cli.set(id, JSON.stringify(document), function (err) {
                  if (err) return next(err);

                  updateDocument(document);
             });                    
         });    
      } else {
          updateDocument(JSON.parse(document));
      }

      function updateDocument (document) {
          // Do some updates ...
          document.title = "Updated post title";

          // Store to redis
          redis_cli.set(id, JSON.strinfy(document), function (err) {
              if (err) return next(err);

              // Document updated successful
              return res.status(200).send('OK');
          });              
      }          
  });
});

我的第一个问题是我如何处理文档?我的方法有什么问题吗?

第二个问题是如何将Redis中的文档刷新回mongodb并从Redis中删除文档?我的目的如下:我只想在用户需要时才将文档存储在Redis中,因此,如果不使用他们的文档,则应将其存储在MongoDB中而不是Redis中。


问题答案:

您的方法似乎很合理。

要“刷新”文档,请在Redis中保留已排序文档ID的排序集,其得分设置为更新时间戳。定期(例如,每分钟)对该集合进行一次ZRANGE处理,以获取“旧”文件(例如,一个小时前的最新更新),然后对每个ID进行一次GET操作,将其写入Mongo,然后删除该文档,来自订购集的ZREM。

*在伪Node.js中 *编辑 未经测试且完全组成的代码示例:

 function updateDocument (document) {
      // Do some updates ...
      document.title = "Updated post title";

      // Store to redis
      multi = redis_cli.multi();
      multi.set(id, JSON.strinfy(document);
      multi.zadd('last_update', time(), id);
      multi.exec(), function (err, replies) {
          if (err) return next(err);

          // Document updated successful
          return res.status(200).send('OK');
      });              
  }

  // call this function periodically, e.g. every minute or so
  function flushOldDocuments () {
      fromTime = time()-3600;
      while (redis_cli.zcount('last_update', '-inf', fromTime) > 0) {
          id = redis_cli.zrangebyscore('last_update', '-inf', fromTime, false, 0, 1); // no scores, offset 0, limit 1 -> get the oldest document
          redis_cli.watch(id);
          Mongo.write(JSON.parse(redis_cli.get(id))); // or something like that
          multi = redis_cli.multi();
          multi.zrem('last_update', id);
          multi.del(id);
          multi.exec(), function(err, replies) {
              // if the watch fails the exec, no harm done and the document will be flushed in an hour
              ...
          };
      };
  }


 类似资料:
  • 问题内容: 我已经使用了C#Redis缓存。 但我想像这样存储数据 这样一键就可以存储所有客户列表,并且可以轻松地在该列表内搜索,分组,过滤客户数据 欢迎使用或回答 问题答案: 您可以使用ServiceStack.Redis高级IRedisTypedClient Typed API 来管理丰富的POCO类型。 首先为具有以下条件的客户获取类型化的Redis客户端: 这将解决用于管理客户POCO的高

  • 我按照web上一些教程使用redis设置Spring缓存,

  • 我有一个具有以下模式的用户集合: 用户将查找用户。名称,必须是唯一的。添加新用户时,我首先执行搜索,如果没有找到这样的用户,我会将新用户文档添加到集合中。搜索用户和添加新用户(如果未找到)的操作不是原子操作,因此,当多个应用程序服务器连接到DB服务器时,可能会同时收到两个具有相同用户名的添加用户请求,从而导致两个添加用户请求都找不到这样的用户,这反过来会导致两个文档具有相同的“user.name”

  • 简而言之:如果您有大量不同大小的文档,其中相对较少的文档达到最大对象大小,那么在MongoDB中存储这些文档的最佳实践是什么? 我有一套文件,比如: 值列表的长度因文档而异。对于大多数文档,它将有几个元素,对于少数文档,它将有数千万个元素,我将达到MongoDB中的最大对象大小限制。问题是,我为那些非常大(而且相对较少)的文档提出的任何特殊解决方案都可能会对我存储小文档的方式产生影响,否则,这些小

  • 问题内容: 我在Firebase上运行了PWA。我的图像文件托管在Firebase存储上。我注意到我的浏览器没有保存从存储系统加载的文件的缓存。浏览器会为每次页面刷新请求文件。这会导致不必要的延迟和流量。 我的JS脚本从Firebase存储的下载链接加载文件,例如:https ://firebasestorage.googleapis.com/v0/b/discipulado-7b14b.apps

  • 问题内容: 我需要将一些时间序列数据存储到Redis中。我有unix时间戳,并且我需要关联一个值(时间戳<->值) 我尝试将时间戳记作为得分(以便我可以在时间戳记上进行zrange)并将值作为成员的排序集。 但是我遇到了一个问题,成员没有重复,而对于不同的时间戳,我的值可以相同。知道如何处理吗?其他数据类型更好吗? 问题答案: 解决此问题的一个简单技巧是将时间戳记和值连接起来。 而不是存储: 您可