我有处理嵌套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 ... }; }; }