nodejs訪問redis時的utils封裝

前言

本文基于redisco-redis,對redis的操作方法進(jìn)行了封裝屁擅,主要實(shí)現(xiàn)以下特性

  • 使用co風(fēng)格訪問DB
  • 整個程序使用單一redis client
  • redis client的初始化在第一次訪問時進(jìn)行
  • 封裝scan命令替代keyssmembers

準(zhǔn)備DB配置文件

// config.js
var redis = {
  RDS_PORT: 6379,
  RDS_HOST: '127.0.0.1',
  RDS_DB: '1'
};

導(dǎo)入第三方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-redisredis提供的所有方法進(jìn)行了co風(fēng)格轉(zhuǎn)化

定義redis client的初始化操作

使用redisCo直接進(jìn)行DB訪問,初始為undifined,第一次進(jìn)行DB訪問時颠黎,使用initClient函數(shù)對該對象進(jìn)行初始化
initClient方法中,首先使用redis創(chuàng)建client,之后配置該client的錯誤監(jiān)聽函數(shù)待德,最后使用co-redis進(jìn)行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對象的構(gòu)造函數(shù)中

  1. 首先使用redis-commands獲取所有redis命令
  2. 對每一個redis命令,在helper中添加與該命令同名的函數(shù)
  3. helper中的每個redis的函數(shù)中枫夺,檢查并初始化redisCo之后将宪,調(diào)用co-redis執(zhí)行該命令

由于co-redis封裝時所提供的redis命令也是從redis-commands中讀取的,從而保證了helper中命令轉(zhuǎn)發(fā)時的正確性
(參見co-redisredis的源碼)

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橡庞,可以通過參數(shù)指定要刪除的keypattern较坛,參數(shù)未指定時,刪除所有的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();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毙死,一起剝皮案震驚了整個濱河市燎潮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扼倘,老刑警劉巖确封,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件除呵,死亡現(xiàn)場離奇詭異,居然都是意外死亡爪喘,警方通過查閱死者的電腦和手機(jī)颜曾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秉剑,“玉大人泛豪,你說我怎么就攤上這事≌炫簦” “怎么了诡曙?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長略水。 經(jīng)常有香客問我价卤,道長,這世上最難降的妖魔是什么渊涝? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任慎璧,我火速辦了婚禮,結(jié)果婚禮上跨释,老公的妹妹穿的比我還像新娘胸私。我一直安慰自己,他們只是感情好鳖谈,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布岁疼。 她就那樣靜靜地躺著,像睡著了一般缆娃。 火紅的嫁衣襯著肌膚如雪五续。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天龄恋,我揣著相機(jī)與錄音,去河邊找鬼凶伙。 笑死郭毕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的函荣。 我是一名探鬼主播显押,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼傻挂!你這毒婦竟也來了乘碑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤金拒,失蹤者是張志新(化名)和其女友劉穎兽肤,沒想到半個月后套腹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡资铡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年电禀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笤休。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡尖飞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出店雅,到底是詐尸還是另有隱情政基,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布闹啦,位于F島的核電站沮明,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏亥揖。R本人自食惡果不足惜珊擂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望费变。 院中可真熱鬧摧扇,春花似錦、人聲如沸挚歧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滑负。三九已至在张,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間矮慕,已是汗流浹背帮匾。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留痴鳄,地道東北人瘟斜。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像痪寻,于是被迫代替她去往敵國和親螺句。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載地址:http://gnucto.blog.51cto.com/3391516/998509 Redis與Me...
    Ddaidai閱讀 21,446評論 0 82
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理橡类,服務(wù)發(fā)現(xiàn)蛇尚,斷路器,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 轉(zhuǎn)自:http://bbs.redis.cn/forum.php?mod=viewthread&tid=481 p...
    木十2036閱讀 806評論 0 7
  • Jetty 是一個開源的servlet容器顾画,它為基于Java的web容器取劫,例如JSP和servlet提供運(yùn)行環(huán)境匆笤。...
    ccq_inori閱讀 232評論 0 2
  • 樹豐老師最近組織了秋季寫書計(jì)劃疚膊,今天下午泡在圖書館一下午的時間尋找寫作的一些方法,為了后期寫作做引導(dǎo)虾标,這或許是最為...
    錦瀟閱讀 394評論 0 2