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

  • 相关阅读:
    Study Plan The TwentySecond Day
    Study Plan The Nineteenth Day
    Study Plan The TwentySeventh Day
    Study Plan The Twentieth Day
    Study Plan The TwentyFirst Day
    python实现进程的三种方式及其区别
    yum makecache
    JSONPath 表达式的使用
    oracle执行cmd的实现方法
    php daodb插入、更新与删除数据
  • 原文地址:https://www.cnblogs.com/Fredric-2013/p/4520134.html
Copyright © 2011-2022 走看看