zoukankan      html  css  js  c++  java
  • mongodb(mongoose-redis-cache)

    在传统的项目中,我们经常会用到缓存来优化数据库的读取,比如java中,我们利用spring的AOP能力,在读写数据库前增加对缓存的操作。

    在node与mongodb的项目中也仍然会存在类似问题,本文参考了mongoose-redis-cache这个插件。

    https://github.com/conancat/mongoose-redis-cache

    该插件还不太完善,但基本的思路是很简单的,初始化一个redis客户端,然后重写mongoose的exec方法,将exec的参数设置为redis的key,将数据库返回的结果设置为对应的value。

    每次操作时优先读取redis。

    代码如下:

    // Generated by CoffeeScript 1.5.0
    var mongooseRedisCache, redis, _;
    
    redis = require("redis");
    
    _ = require("underscore");
    
    mongooseRedisCache = function(mongoose, options, callback) {
      var client, host, pass, port, redisOptions;
      if (options == null) {
        options = {};
      }
      host = options.host || "";
      port = options.port || "";
      pass = options.pass || "";
      redisOptions = options.options || {};
      mongoose.redisClient = client = redis.createClient(port, host, redisOptions);
      if (pass.length > 0) {
        client.auth(pass, function(err) {
          if (callback) {
            return callback(err);
          }
        });
      }
    
    //这里做了改动,原来是execFind,在我当前的Mongoose版本下无法使用 mongoose.Query.prototype._exec
    = mongoose.Query.prototype.exec; mongoose.Query.prototype.exec = function(callback) { var cb, expires, fields, key, model, query, schemaOptions, self; self = this; model = this.model; query = this._conditions; options = this._optionsForExec(model); fields = _.clone(this._fields); schemaOptions = model.schema.options; expires = schemaOptions.expires || 60; if (!schemaOptions.redisCache && options.lean) { return mongoose.Query.prototype._exec.apply(self, arguments); } key = JSON.stringify(query) + JSON.stringify(options) + JSON.stringify(fields); cb = function(err, result) { var docs; if (err) { return callback(err); } if (!result) { return mongoose.Query.prototype._exec.call(self, function(err, docs) { var str; if (err) { return callback(err); } str = JSON.stringify(docs); client.set(key, str); client.expire(key, expires); return callback(null, docs); }); } else { docs = JSON.parse(result); return callback(null, docs); } }; client.get(key, cb); return this; }; }; module.exports = mongooseRedisCache;

    写测试用例如下:

    var mongoose = require('mongoose');
    
    var async = require('async');
    var mongooseRedisCache = require("mongoose-redis-cache");
    mongooseRedisCache(mongoose);
    var Schema = mongoose.Schema;
    
    mongoose.connect('mongodb://localhost/cachetest');
    
    var user = new Schema({
        username:{
            type:String,
            index:true
        },
        password:String
    });
    
    user.set('redisCache', true);
    
    var userModel = mongoose.model('user', user);
    
    var entity = new userModel({
        username:'fredric',
        password:'sinny'
    });
    
    var users = [];
    for(var i = 0; i < 1000; i++){
        users.push({
            username:'fredric' + i,
            password:'sinny' + i
        });
    }
    
    function testCache(){
    
        function datainit(item,cb){
            var entity = new userModel(item);
            entity.save(function(err){
                cb(err);
            });
        }
        
        async.mapSeries(users, datainit, function(err, results){
            
            console.log('datainit finished');
            
            var timestamp = new Date().valueOf();
            
            var round = [];
            for(var i = 0; i < 2000; i++){
                round.push(i);
            }
            
            //利用缓存
            function test(item,cb){
                query = userModel.find({'username':'fredric101'});
                query.lean();
                query.exec(function(err, result){
                    cb(err);
                });
            }
            
            
            //不利用缓存
            function test_nocache(item,cb){
                query = userModel.find({}).setOptions({nocache: true});
                query.where("username", "fredric101");
                query.exec(function(err, result){
                    cb(err);
                });
            }
            
            async.mapSeries(round, test_nocache, function(err, results){
                console.log(new Date().valueOf() - timestamp);
            });
        });    
    }
    testCache();

    测试结果还是比较明显的,在我本地笔记本上(安装redis + mongodb),上述测试用例执行:

    1、无缓存、无索引:21501ms

    2、无缓存、有索引:1966ms

    3、有缓存、有索引:281ms

  • 相关阅读:
    【字符串题目】poj 3096 Surprising Strings
    【转载】:【博弈论】博弈的学习和总结
    【博弈论】hihocoder
    转载:SPFA算法学习
    马克思所言:
    【NOIP2013】火柴排队
    【NOIP2013】【P1441】花匠
    【JZOI2002】【BZOJ1477】【P1371】青蛙的约会
    【P1373】奶牛的卧室
    2016.9.16 の 測試
  • 原文地址:https://www.cnblogs.com/Fredric-2013/p/4520134.html
Copyright © 2011-2022 走看看