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 ...
随机推荐
- VBA中常用技巧
常量定义 Public Const i as Integer = 1 自定义类型 Type mytype i as Integer b as Boolean s as String end ...
- Ubuntu 16 安装odoo10 实录
安装Ubuntu 16,省略 安装时,默认用户名为 odoo ubuntu 16开始 使用 systemd 管理服务,但是systemd 兼容 sysv init 脚本 下载 odoo源码 从 htt ...
- iptables示例
[root@iZ23um2lv3tZ ~]# more /etc/sysconfig/iptables # Generated by iptables-save v1. :: *filter :INP ...
- 深入研究C语言 第一篇
一. 研究过程 1.第一章:创建编译环境: 我们首先下载TC2.0,找到其中与编译连接相关的程序和文件: (1) 编译器:TCC.exe (2) 连接器:tllike.exe (3) 相关文件:c0s ...
- Ajax Step By Step4
第四,[$.ajax()] $.ajax()是所有 ajax 方法中最底层的方法,所有其他方法都是基于$.ajax()方法的封装.这个方法只有一个参数,传递一个各个功能键值对的对象. $.ajax() ...
- hasOwnProperty和in
返回一个布尔值,指出一个对象是否具有指定名称的属性. hasOwnProperty 此方法无法检查该对象的原型链中是否具有该属in 可以检查原型链中是否具有该属
- 如何在SCENEKIT使用SWIFT RUNTIME动态加载COLLADA文件
问题:今天接到一个项目,负责弄需求的美眉跟我讲能不能做一个原型能够加载Collada文件,流程如下: 用户用app下载Collada 压缩包(如内购项目) 压缩包解压 展示Collada文件里的内容 ...
- 通俗易懂的 JSon解析处理
1.主要用到的类: 主要用到了JavaScriptSerializer类,该类在System.Web.Script.Serialization命名空间(在System.Web.Extensions.d ...
- 《Linux内核分析》之第四章读书笔记
4.1多任务 多任务操作系统:同时并发地交互执行多个进程的操作系统 多任务操作系统会使多个进程处于堵塞或者睡眠状态.这些任务尽管位于内存,但是并不处于可运行状态.这些进程利用内核堵塞自己,直到某一事件 ...
- 圆角卖萌式登录表单和width的百分比值
1.圆角恶意卖萌登录表单 小组要做一个网站,大学生社区那种,然后要做登陆界面然后还要做好看的登录界面,然后在书上看到了一个很漂亮的登陆界面,说来和一般的登陆界面没什么不同只是登录表单的边角被柔化了,变 ...