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
mongodb(mongoose-redis-cache)的更多相关文章
- 现在 做java 构架(RabbitMQ redis mysql )之类的
现在 做java 构架(RabbitMQ redis mysql )之类的
- mongoDB (mongoose、增删改查、聚合、索引、连接、备份与恢复、监控等等)
MongoDB - 简介 官网:https://www.mongodb.com/ MongoDB 是一个基于分布式文件存储的数据库,由 C++ 语言编写,旨在为 WEB 应用提供可扩展的高性能数据存储 ...
- HTTP协议(缓存机制Cache)
HTTP的缓存 至于响应消息的实体,与请求消息的实体内容相似,这里只借绍下User-Agent头 User-Agent头域的内容包含发出请求的用户信息. Cache-Control头域(请求和应答通用 ...
- MongoDB(课时29 MapReduce)
3.7.4 MapReduce MapReduce 是整个大数据的精髓所在(实际中别用,因为在MongoDB中属于最底层操作). MapReduce是一种计算模型,简单的说就是将大批量的工作分解执行, ...
- MongoDB(课时24 全文索引)
3.6.3 全文索引 在一些信息管理平台上经常需要进行信息模糊查询,最早的时候是利用了某个字段上实现的模糊查询,但这个时候返回的信息并不会很准确,因为只能够查A字段或B字段,而在MongoDB里面实现 ...
- MongoDB(课时17 更新函数)
3.4.3 数据更新操作 MongoDB数据存的是副本数据, 最终的数据还要保存在传统的数据库里,所以如果关系型数据库里数据变了,最好的方法是删除里面的MongoDB数据重新插入. 在MongoDB里 ...
- NoSQL高级培训课程-HBase&&MongoDB(两天版)
课程大纲 主题 时间 主题 列数据库 (第1天) 上午 HBase发展简史-Google BigTable的开源实现 HBase基础:安装部署.管理命令.运行监控和开发接口: HBase专题:服务组件 ...
- Debian Buster 配置 Laravel 运行环境(nginx + redis + supervisor)
1 目标 将开发完成的 Laravel 项目布署于 Debian 之上.由于项目要求使用 horizon 官方扩展,要求 PHP7.1+,故采用 Debian buster (下一版) 2 材料 IP ...
- 配置到 Framework GAC(Global Assembly Cache) Assembly
配置到 Framework 通常有两种方法,一种是直接把它放到GAC(Global Assembly Cache作用是可以存放一些有很多程序都要用到的公共Assembly)中 :另一种是把它们放到具体 ...
- MongoDB(课时7 逻辑运算)
3.4.2.2 逻辑运算 逻辑运算主要三种类型:与($and),或($or),非($not.$nor). 范例:查询年龄在20~21岁的学生信息 db.students.find({"age ...
随机推荐
- Dreamweaver扩展注意事项
对Dreamweaver扩展做了一些整理. 扩展开发扩展(Extension),是应用程序给用户预留的二次开发接口.Dreamweaver提供了对菜单,插入栏(Insertbar),浮动框等GUI部件 ...
- Oracle 安装及其遇到的问题
Oracle安装过程其实有很多的文档可以参考. 以oracle11g release版本为例: 从官网下载下来的zip ,包含两个部分,win32_11gR2_database_1of2.zip 以及 ...
- TaskScheduler的启动
<深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...
- k-sum问题
给定一个数组,里面的是任意整数,可能有重复,再给定一个目标T,从数组中找出所有和为T的K个数,要求结果中没有重复. Note: Elements in a quadruplet (a,b,c,d) m ...
- Android自定义View的实现方法,带你一步步深入了解View(四)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了,回 ...
- Area区域
1.mvc4.0新增的area区域机制,可以协助你在架构较为大型的项目,让独立性较高的部分功能独立成一个MVC子网站,以降低网站与网站之间的耦合性,也可以通过area的切割,让多人同时开发同一个项目时 ...
- win使用MSYS2安装Qt开发环境
原文链接 MSYS2 下载地址: pacman的具体用法 有pacman的具体使用方法.我们首先对系统升级 我们首先对系统升级 pacman -Syu 就会检测整个系统可以升级的组件,并自动下载安装, ...
- linux进程间通信-共享内存
转载:http://www.cnblogs.com/fangshenghui/p/4039720.html 一 共享内存介绍 共享内存可以从字面上去理解,就把一片逻辑内存共享出来,让不同的进程去访问它 ...
- Ubuntu搭建Ruby on Rails环境
安装Ruby 由于Ubuntu的apt包管理器的ruby版本过旧,故考虑从源码编译安装.这里以安装ruby2.3.0为例: sudo apt-get install build-essential z ...
- Titanium系列--对Window和View的一点理解
1. window相当于一块屏幕,view相当于一个div层.window拥有全屏和模态化属性,view则没有这2个属性. 2. 创建一个window作为我们的APP的屏幕,之后我们将添加其他元素来丰 ...