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 ...
随机推荐
- vs2015 command prompt here
网上搜的很多方法都不能用,比如:http://app.paraesthesia.com/CommandPromptHere/ 主要是都搞错了注册表路径,写成了: HKCR,Directory\Shel ...
- python的正负无穷float("inf")的用法
今天,在看书的时候看到这么一个例子: 这是用来求解 从某个数字列表中找出俩个彼此最接近但是不相等的数(俩者之间的绝对差是最小的): >>> from random import ra ...
- phpStudy 的Apache虚拟主机配置
放弃了wamp,朋友介绍了phpstudy,不错的一款软件,关键是能自由切换php版本.相关的阿帕奇虚拟主机配置参考:http://www.th7.cn/system/win/201506/10846 ...
- 我是一只IT小小鸟——读后感
读到书名我便知道,我们是一类人,都是现在在学IT的学生或者打算以后从事IT行业的人,或者现在正在从事IT行业的人,不同区域的人,不同性格的人,不同家庭背景的人,不同,很多的不同,但是我们都有相同的迷惘 ...
- c# 调用 matlab
如果本机没有安装Matlab 需要安装一个叫 MCRInstaller 的东西 运行环境 如果安装后 需要把D:\MATLAB\R2013a\bin\win64; 写入环境变量 (路径根据实际情况改 ...
- Oracle sys和system用户、sysdba 和sysoper系统权限、sysdba和dba角色的区别
sys和system用户区别 1)最重要的区别,存储的数据的重要性不同 sys所有oracle的数据字典的基表和视图都存放在sys用户中,这些基表和视图对于oracle的运行是至关重要的,由数据库自己 ...
- WPF Combobox样式
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}&qu ...
- 【温故Delphi】双击工程文件打开软件
问题描述 大部分软件都有鼠标双击文件,就能打开所关联的软件并打开所选工程,这是如何做到的呢? 把文件关联到一个程序中,双击文件来启动程序,那么这个文件名称就是这个程序的命令行的一个参数. 所以要想实现 ...
- 【温故Delphi】之VCL消息机制小结
TObject消息分派 procedure Dispatch(var Message); virtual; #负责分派消息到特定VCL组件的事件处理函数 procedure DefaultHandle ...
- 1036. Crypto Columns 2016 11 02
/* 对于题目多读几遍,然后再关键字排序的时候,把对应的数组序号也排序, EYDE MBLR THAN MEKT ETOE EOTH MEETME B ...