前言
本文基于redis和co-redis,对redis的操作方法进行了封装,主要实现以下特性
- 使用
co
风格访问DB - 整个程序使用单一
redis client
-
redis client
的初始化在第一次访问时进行 - 封装
scan
命令替代keys
和smembers
准备DB配置文件
// config.js
var redis = {
RDS_PORT: 6379,
RDS_HOST: '127.0.0.1',
RDS_DB: '1'
};
导入第三方Package
var commands = require('redis-commands');
var redis = require('redis');
var wrapper = require('co-redis');
var config = require('./config'); //配置文件
- redis-commands提供了所有redis支持的命令
- redis封装了nodejs访问redis的所有操作
- co-redis对redis提供的所有方法进行了
co
风格转化
定义redis client的初始化操作
使用redisCo
直接进行DB访问,初始为undifined
,第一次进行DB访问时,使用initClient
函数对该对象进行初始化
initClient
方法中,首先使用redis创建client
,之后配置该client
的错误监听函数,最后使用co-redis进行co
化
var redisCo;
var initClient = function() {
var client = redis.createClient(config.redis.RDS_PORT,
config.redis.RDS_HOST, {
db: config.redis.RDS_DB
});
client.on('error', function(err) {
console.log('Error ' + err);
});
redisCo = wrapper(client);
};
定义helper对象作为该utils模块的对外接口
在helper
对象的构造函数中
- 首先使用redis-commands获取所有
redis
命令 - 对每一个
redis
命令,在helper
中添加与该命令同名的函数 -
helper
中的每个redis
的函数中,检查并初始化redisCo
之后,调用co-redis执行该命令
由于co-redis封装时所提供的redis命令也是从redis-commands中读取的,从而保证了helper中命令转发时的正确性
(参见co-redis和redis的源码)
var helper = function() {
var self = this;
commands.list.forEach(function(command) {
self[command] = function*() {
if (redisCo === undefined) {
initClient();
}
var res = {};
var params = arguments;
res = yield redisCo[command].apply(this, params);
return res;
};
});
};
// 省略
module.exports = new helper();
为helper添加自定义方法
- cleanup
用于批量删除redis
中的key
,可以通过参数指定要删除的key
的pattern
,参数未指定时,删除所有的key
helper.prototype.cleanup = function*(count) {
var partern = '';
switch (count) {
case '0':
partern = '0x01:*';
break;
case '1':
partern = '0x02:*';
break;
case '2':
partern = '0x10:*';
break;
case '3':
partern = '0x90:*';
break;
case '4':
partern = '0x91:*';
break;
default:
partern = '*';
break;
}
var keys = yield this.keys(partern);
if (keys.length !== 0) {
yield this.del(keys);
}
};
- scanKeys
用于替代keys命令获取符合指定pattern
的所有key
helper.prototype.scanKeys = function*(pattern) {
var ret = [];
var cursor = 0;
while (true) {
var res = yield this.scan(cursor, 'MATCH', pattern, 'COUNT', 10);
cursor = parseInt(res[0]);
ret = ret.concat(res[1]);
if (cursor === 0) {
break;
}
}
return ret;
- scanMembers
用于替代smember
命令获取指定set
的所有成员
helper.prototype.scanMembers = function*(key) {
var ret = [];
var cursor = 0;
while (true) {
var res = yield this.sscan(key, cursor, 'COUNT', 10);
cursor = parseInt(res[0]);
ret = ret.concat(res[1]);
if (cursor === 0) {
break;
}
}
return ret;
};
- 其他
完整的代码
//dbhelper.js
'use strict';
var commands = require('redis-commands');
var redis = require('redis');
var wrapper = require('co-redis');
var config = require('../config');
var redisCo;
var initClient = function() {
var client = redis.createClient(config.redis.RDS_PORT,
config.redis.RDS_HOST, {
db: config.redis.RDS_DB
});
client.on('error', function(err) {
console.log('Error ' + err);
});
redisCo = wrapper(client);
};
var helper = function() {
var self = this;
commands.list.forEach(function(command) {
self[command] = function*() {
if (redisCo === undefined) {
initClient();
}
var res = {};
var params = arguments;
res = yield redisCo[command].apply(this, params);
return res;
};
});
};
helper.prototype.cleanup = function*(count) {
var partern = '';
switch (count) {
case '0':
partern = '0x01:*';
break;
case '1':
partern = '0x02:*';
break;
case '2':
partern = '0x10:*';
break;
case '3':
partern = '0x90:*';
break;
case '4':
partern = '0x91:*';
break;
default:
partern = '*';
break;
}
var keys = yield this.keys(partern);
if (keys.length !== 0) {
yield this.del(keys);
}
};
helper.prototype.scanKeys = function*(pattern) {
var ret = [];
var cursor = 0;
while (true) {
var res = yield this.scan(cursor, 'MATCH', pattern, 'COUNT', 10);
cursor = parseInt(res[0]);
ret = ret.concat(res[1]);
if (cursor === 0) {
break;
}
}
return ret;
};
helper.prototype.scanMembers = function*(key) {
var ret = [];
var cursor = 0;
while (true) {
var res = yield this.sscan(key, cursor, 'COUNT', 10);
cursor = parseInt(res[0]);
ret = ret.concat(res[1]);
if (cursor === 0) {
break;
}
}
return ret;
};
module.exports = new helper();