/**
?*?redis操作示例
?*/??
//?準(zhǔn)備工作:npm?install?redis?co-redis?(--save)???
//?開發(fā)機(jī)ip:???
//?默認(rèn)端口:6379??
//?文檔參考:https://www.npmjs.com/package/redis?????????(node-redis)??
//?文檔參考:https://www.npmjs.com/package/co-redis??????(co-redis)??
//?文檔參考:http://www.redis.cn/commands.html???????????????(redis命令)??
//?開發(fā)機(jī)測(cè)試配置:?jiǎn)?dòng)redis服務(wù)后加?--protected-mode?no?選項(xiàng)?使其允許遠(yuǎn)程連接??
var?co?=?require('co');??
var?redis?=?require('redis');??
var?wrapper?=?require('co-redis');??
var?log?=?Log('models.redis');??
//var?redisClient?=?redis.createClient();??
//?redis配置參數(shù)??
var?redis_config?=?{??
"host":?"",??
"port":?6379??
};??
var?redisClient?=?redis.createClient(redis_config);??
//?數(shù)據(jù)庫(kù)選擇/*?*?redis默認(rèn)連接數(shù)據(jù)庫(kù)0,可以利用select選擇指定數(shù)據(jù)庫(kù)0~15?*?使用示例:?*???
redisClient.select("15",?function?(err)?{?*?if?(err)?{?*?return?false;?*?}?else?{?*?console.log('connect?success');?*?}?*?});?*/??
或者直接??
var?redisClient?=?redis.createClient('redis://100.131.26.110:8009?database=0');??
//?使用co-redis包裝redisClient??
var?redisCo?=?wrapper(redisClient);??
//?利用co-redis包裝將redis命令以返回值形式直接輸出??
/*co(function*?()?{
??var?set?=?yield?redisCo.set('test',?33);
??console.log(set);
??console.log(yield?redisCo.get('test'));?//?logs?33?
??redisClient.quit();
}).catch(function(e)?{
});*/??
//?redis命令使用示例????
/*
?*?基本示例:
?*?redisClient.set('key',?'value',?function?(res,?reply)?{});
?*
?*?命令參數(shù):
?*?1、字符串
?*?2咆疗、數(shù)組?(注:非所有命令均可用)
?*?(對(duì)于hash操作副砍,賦值可使用json)
?*?(后跟回調(diào)函數(shù)[可選])?(利用co-redis可以將命令以返回值形式輸出)?
?*?
?*?使用示例(不同參數(shù)樣式實(shí)現(xiàn)相同功能)
?*?
?*?client.hmset(["key",?"test?keys?1",?"test?val?1",?"test?keys?2",?"test?val?2"],?function?(err,?res)?{});
?*?client.hmset("key",?["test?keys?1",?"test?val?1",?"test?keys?2",?"test?val?2"],?function?(err,?res)?{});
?*?client.hmset("key",?"test?keys?1",?"test?val?1",?"test?keys?2",?"test?val?2",?function?(err,?res)?{});???
?*
?*?client.set("some?key",?"some?val");
?*?client.set(["some?other?key",?"some?val"]);
?*
?*?client.hmset(hash,?obj[,?callback])??????(此處可以使用json)????
?*?client.hmset(hash,?key1,?val1,?...?keyn,?valn,?[callback])
?*/??
//?redis數(shù)據(jù)類型命令匯總??
/*
??*?string?字符串
??*?????命令??????????????????行為??????????????????????????????????????????????返回值?????????????????????使用示例(略去回調(diào)函數(shù))
??*?????set?????????設(shè)置存儲(chǔ)在給定鍵中的值??????????????????????OK?????????????????????????set('key',?'value')
??*?????get?????????獲取存儲(chǔ)在給定鍵中的值?????????????????????value/null??????????get('key')
??*?????del?????????刪除存儲(chǔ)在給定鍵中的值(任意類型)????1/0????????????????????????del('key')
??*?????incrby??將鍵存儲(chǔ)的值加上整數(shù)increment?????????????????????????????????????????incrby('key',?increment)
??*?????decrby??將鍵存儲(chǔ)的值減去整數(shù)increment?????????????????????????????????????????decrby('key',?increment)
??*?????incrbyfloat?將鍵存儲(chǔ)的值加上浮點(diǎn)數(shù)increment????????????????????????????????incrbyfloat('key',?increment)???
??*?????append??將值value追加到給定鍵當(dāng)前存儲(chǔ)值的末尾???????????????????????????append('key',?'new-value')
??*?????getrange????獲取指定鍵的index范圍內(nèi)的所有字符組成的子串????????????getrange('key',?'start-index',?'end-index')
??*?????setrange????將指定鍵值從指定偏移量開始的子串設(shè)為指定值???????????setrange('key',?'offset',?'new-string')
??*?????
??*?list?列表
??*???命令????????????????????行為??????????????????????????????????????????????返回值?????????????????????使用示例(略去回調(diào)函數(shù))
??*?????rpush???????將給定值推入列表的右端?????????????????????當(dāng)前列表長(zhǎng)度??????rpush('key',?'value1'?[,'value2'])?(支持?jǐn)?shù)組賦值)
??*?????lrange??獲取列表在給定范圍上的所有值??????????array???????????????????????lrange('key',?0,?-1)?(返回所有值)
??*?????lindex??獲取列表在給定位置上的單個(gè)元素?????????????????????????????????????lindex('key',?1)
??*?????lpop????????從列表左端彈出一個(gè)值罢维,并返回被彈出的值?????????????????????lpop('key')
??*?????rpop????????從列表右端彈出一個(gè)值棚菊,并返回被彈出的值?????????????????????rpop('key')
??*?????ltrim???????將列表按指定的index范圍裁減????????????????????????????????????????????????ltrim('key',?'start',?'end')
??*
??*?set?集合
??*?????命令??????????????????行為??????????????????????????????????????????????返回值?????????????????????使用示例(略去回調(diào)函數(shù))
??*?????sadd????????????將給定元素添加到集合??????????????????????插入元素?cái)?shù)量??????sadd('key',?'value1'[,?'value2',?...])?(不支持?jǐn)?shù)組賦值)(元素不允許重復(fù))
??*?????smembers????返回集合中包含的所有元素????????????????array(無(wú)序)???????????smembers('key')
??*?????sismenber???檢查給定的元素是否存在于集合中?1/0?????????????????????????sismenber('key',?'value')
??*?????srem????????????如果給定的元素在集合中卿操,則移除此元素?1/0??????????????srem('key',?'value')
??*?????scad????????????返回集合包含的元素的數(shù)量????????????????????????????????????????????????sacd('key')???
??*?????spop????????????隨機(jī)地移除集合中的一個(gè)元素,并返回此元素????????????????spop('key')
??*?????smove???????????集合元素的遷移?????????????????????????????????????????????????????????????????smove('source-key',?'dest-key',?'item')
??*?????sdiff???????????返回那些存在于第一個(gè)集合待诅,但不存在于其他集合的元素(差集)???sdiff('key1',?'key2'[,?'key3',?...])???
??*?????sdiffstore??將sdiff操作的結(jié)果存儲(chǔ)到指定的鍵中?????????????????????????sdiffstore('dest-key',?'key1',?'key2'?[,'key3'?,...])???
??*?????sinter??????返回那些同事存在于所有集合中的元素(交集)???????????????sinter('key1',?'key2'[,?'key3',?...])
??*?????sinterstore?將sinter操作的結(jié)果存儲(chǔ)到指定的鍵中????????????????????????sinterstore('dest-key',?'key1',?'key2'?[,'key3'?,...])??
??*?????sunion??????返回那些至少存在于一個(gè)集合中的元素(并集)???????????????sunion('key1',?'key2'[,?'key3',?...])
??*?????sunionstore?將sunion操作的結(jié)果存儲(chǔ)到指定的鍵中????????????????????????sunionstore('dest-key',?'key1',?'key2'?[,'key3'?,...])??
??*
??*?hash?散列
??*?????命令??????????????????行為??????????????????????????????????????????????返回值?????????????????????使用示例(略去回調(diào)函數(shù))
??*?????hset????????????在散列里面關(guān)聯(lián)起給定的鍵值對(duì)??????1(新增)/0(更新)?hset('hash-key',?'sub-key',?'value')????(不支持?jǐn)?shù)組颈走、字符串)
??*?????hget????????????獲取指定散列鍵的值???????????????????????????????????????????????????????????hget('hash-key',?'sub-key')
??*?????hgetall?????獲取散列包含的鍵值對(duì)??????????????????????json????????????????????????hgetall('hash-key')
??*?????hdel????????????如果給定鍵存在于散列里面,則移除這個(gè)鍵?????????????????hdel('hash-key',?'sub-key')
??*?????hmset???????????為散列里面的一個(gè)或多個(gè)鍵設(shè)置值?OK??????????????????????????hmset('hash-key',?obj)
??*?????hmget???????????從散列里面獲取一個(gè)或多個(gè)鍵的值?array???????????????????????hmget('hash-key',?array)
??*?????hlen????????????返回散列包含的鍵值對(duì)數(shù)量????????????????????????????????????????????????hlen('hash-key')
??*?????hexists?????檢查給定鍵是否在散列中?????????????????1/0?????????????????????????hexists('hash-key',?'sub-key')
??*?????hkeys???????????獲取散列包含的所有鍵??????????????????????array???????????????????????hkeys('hash-key')
??*?????hvals???????????獲取散列包含的所有值??????????????????????array???????????????????????hvals('hash-key')
??*?????hincrby?????將存儲(chǔ)的鍵值以指定增量增加???????????返回增長(zhǎng)后的值?hincrby('hash-key',?'sub-key',?increment)?(注:假如當(dāng)前value不為為字符串咱士,則會(huì)無(wú)輸出立由,程序停止在此處)
??*?????hincrbyfloat????將存儲(chǔ)的鍵值以指定浮點(diǎn)數(shù)增加
??*?????
??*?????
??*?zset?有序集合
??*?????命令??????????????????行為??????????????????????????????????????????????返回值?????????????????????使用示例(略去回調(diào)函數(shù))
??*?????zadd????????????將一個(gè)帶有給定分支的成員添加到有序集合中????????????????zadd('zset-key',?score,?'key')?(score為int)
??*?????zrange??????根據(jù)元素在有序排列中的位置轧钓,從中取出元素
??*?????zrangebyscore???獲取有序集合在給定分值范圍內(nèi)的所有元素
??*?????zrem????????????如果給定成員存在于有序集合,則移除
??*?????zcard???????????獲取一個(gè)有序集合中的成員數(shù)量??????有序集的元素個(gè)數(shù)????zcard('key')
??*
??*/??
//?redis其他常用命令匯總??
/*
?????*?keys命令組
?????*??命令??????????????????行為??????????????????????????????????????????????返回值?????????????????????使用示例(略去回調(diào)函數(shù))
?????*??del?????????????刪除一個(gè)(或多個(gè))keys???????????被刪除的keys的數(shù)量?????del('key1'[,?'key2',?...])
?????*??exists??????查詢一個(gè)key是否存在?????????????????????????????1/0?????????????????????exists('key')
?????*??expire??????設(shè)置一個(gè)key的過期的秒數(shù)???????????????????????1/0?????????????????????expire('key',?seconds)
?????*??pexpire?????設(shè)置一個(gè)key的過期的毫秒數(shù)??????????????????1/0?????????????????????pexpire('key',?milliseconds)????
?????*??expireat????設(shè)置一個(gè)UNIX時(shí)間戳的過期時(shí)間????????????1/0?????????????????????expireat('key',?timestamp)
?????*??pexpireat???設(shè)置一個(gè)UNIX時(shí)間戳的過期時(shí)間(毫秒)?1/0????????????????????pexpireat('key',?milliseconds-timestamp)
?????*??persist?????移除key的過期時(shí)間??????????????????????????????????1/0?????????????????????persist('key')
?????*??sort????????????對(duì)隊(duì)列锐膜、集合毕箍、有序集合排序???????排序完成的隊(duì)列等??sort('key'[,?pattern,?limit?offset?count])
?????*??
?????*??flushdb?????清空當(dāng)前數(shù)據(jù)庫(kù)
?????*??
???*/??
co(function*?()?{??
//var?set?=?yield?redisCo.sadd('set-key',?[item,?item1,?item2,?item3,?item4]);??
var?json?=?{??
'sub-key5':?'value6',??
'sub-key7':?'value7'??
??};??
var?array?=?['sub-key4',?'sub-key5'];??
//var?hash?=?yield?redisCo.hset('hash-key',?'sub-key4',?'value4');??
var?hash?=?yield?redisCo.hgetall('hash-key');??
????console.log(hash);??
??redisClient.quit();??
});??
//?redis事務(wù)(支持連貫操作)??
/*
?*?常用命令
?*??multi()?事務(wù)
?*??exec([callback])?執(zhí)行事務(wù)
?*??discard?放棄事務(wù)
?*??watch?監(jiān)視指定的鍵值
?*??unwatch?取消監(jiān)視
?*?
?*?命令用法:
?*??MULTI
?*??????MULTI?命令用于開啟一個(gè)事務(wù),它總是返回?OK?道盏。?
?*??????MULTI?執(zhí)行之后而柑,?客戶端可以繼續(xù)向服務(wù)器發(fā)送任意多條命令,?
?*??????這些命令不會(huì)立即被執(zhí)行荷逞,?而是被放到一個(gè)隊(duì)列中琼懊,?當(dāng)?EXEC命令被調(diào)用時(shí)捂掰,?所有隊(duì)列中的命令才會(huì)被執(zhí)行。
?*??????另一方面,?通過調(diào)用?DISCARD?檬输,?客戶端可以清空事務(wù)隊(duì)列扼菠,?并放棄執(zhí)行事務(wù)奈梳。
?*??EXEC
?*??????EXEC?命令的回復(fù)是一個(gè)數(shù)組砚蓬,?數(shù)組中的每個(gè)元素都是執(zhí)行事務(wù)中的命令所產(chǎn)生的回復(fù)。?
?*??????其中膝迎,?回復(fù)元素的先后順序和命令發(fā)送的先后順序一致粥帚。
?*??DISCARD
?*??????當(dāng)執(zhí)行?DISCARD?命令時(shí),?事務(wù)會(huì)被放棄限次,?事務(wù)隊(duì)列會(huì)被清空芒涡,?并且客戶端會(huì)從事務(wù)狀態(tài)中退出
?*??WATCH
?*??????WATCH?命令可以為?Redis?事務(wù)提供?check-and-set?(CAS)行為。
?*??????被?WATCH?的鍵會(huì)被監(jiān)視卖漫,并會(huì)發(fā)覺這些鍵是否被改動(dòng)過了拖陆。?
?*??????如果有至少一個(gè)被監(jiān)視的鍵在?EXEC?執(zhí)行之前被修改了,?那么整個(gè)事務(wù)都會(huì)被取消懊亡,?
?*??????EXEC?返回nil-reply來表示事務(wù)已經(jīng)失敗依啰。
?*??
?*??????WATCH?使得?EXEC?命令需要有條件地執(zhí)行:?
?*??????事務(wù)只能在所有被監(jiān)視鍵都沒有被修改的前提下執(zhí)行,?如果這個(gè)前提不能滿足的話店枣,事務(wù)就不會(huì)被執(zhí)行速警。
?*??
?*??????WATCH?命令可以被調(diào)用多次。?對(duì)鍵的監(jiān)視從?WATCH?執(zhí)行之后開始生效鸯两,?直到調(diào)用?EXEC?為止闷旧。
?*
?*??????當(dāng)?EXEC?被調(diào)用時(shí),?不管事務(wù)是否成功執(zhí)行钧唐,?對(duì)所有鍵的監(jiān)視都會(huì)被取消忙灼。
?*??????另外,?當(dāng)客戶端斷開連接時(shí),?該客戶端對(duì)鍵的監(jiān)視也會(huì)被取消该园。
?*??UNWATCH
?*??????使用無(wú)參數(shù)的?UNWATCH?命令可以手動(dòng)取消對(duì)所有鍵的監(jiān)視酸舍。
?*
?*?使用示例:
?*??1、連貫操作
?*??????client.multi().incr('key').incr('key').exec(function?(err,?reply)?{});
?*
?*??2里初、常規(guī)操作
?*??????multi?=?client.multi();
?*??????multi.incr('key');
?*??????multi.incr('key');
?*??????multi.exec(function?(err,?replies)?{});
?*
?*??3啃勉、取巧操作
?*??????client.multi([
?*??????????["mget",?"multifoo",?"multibar",?redis.print],
?*??????????["incr",?"multifoo"],
?*??????????["incr",?"multibar"]
?*??????]).exec(function?(err,?replies)?{
?*??????????console.log(replies);
?*??????});?
?*
?*/??
//?事件監(jiān)聽???
/*
?*?事件:ready、connect双妨、reconnecting淮阐、end、warning刁品、error
?*?執(zhí)行順序:?ready?>?connect?>?end(quit觸發(fā))
?*?error事件需要設(shè)置監(jiān)聽(必選)
?*
?*?使用示例:
?*?redisClient.on("ready",?function(err)?{??
?*??if?(err)?return?false;
?*??console.log("ready");
?*?});
?*/??
redisClient.on("error",?function?(err)?{??
console.log("Error?"?+?err);??
});??
//?數(shù)據(jù)操作(未用co-redis包裝的寫法)??
//?string(增泣特、刪、改挑随、查)??
/*redisClient.set('string?key',?'string?value',?function?(err,?reply)?{
????if?(err)?return?false;
????console.log(reply);?????//?設(shè)置成功,返回值為OK,數(shù)據(jù)更改直接更改對(duì)應(yīng)的value即可状您,返回值也為OK。
});
redisClient.set('string?key1',?'string?value1',?redis.print);???????//?此種方式直接在命令行打印返回值镀裤。
redisClient.get('string?key',?function?(err,?reply)?{
????if?(err)?return?false;
????console.log(reply);?????//?取值成功竞阐,返回指定鍵值對(duì)應(yīng)的value,若鍵值不存在缴饭,返回null
});
redisClient.exists('string?key2',?function?(err,?reply)?{
????if?(err)?return?false;
????console.log(reply);?????//?鍵存在暑劝,返回1,否則返回0
});
redisClient.del('string?key1',?function?(err,?reply)?{
????if?(err)?return?false;
????console.log(reply);?????//?刪除成功颗搂,返回1担猛,否則返回0(對(duì)于不存在的鍵進(jìn)行刪除操作,同樣返回0)
});
redisClient.randomkey(function?(err,?reply)?{
????if?(err)?return?false;
????console.log(reply);?????//?隨機(jī)返回一個(gè)鍵
});
redisClient.set('string?key',?'string?value',?function(err,?reply)?{
????if?(err)?return?false;
????console.log(reply);
});
redisClient.expire('string?key',?1,?function(err,?reply)?{
????if?(err)?return?false;
????console.log(reply);
});
redisClient.get('string?key',?function?(err,?reply)?{
????if?(err)?return?false;
????console.log(reply);?????//?取值成功丢氢,返回指定鍵值對(duì)應(yīng)的value,若鍵值不存在傅联,返回null
});
setTimeout(function?()?{
????redisClient.get('string?key',?function?(err,?reply)?{
????????if?(err)?console.log(err);
????????console.log(reply);?????//?取值成功,返回指定鍵值對(duì)應(yīng)的value,若鍵值不存在疚察,返回null
????});
},?1100);*/??
//?list??
//?set???
//?sorted?set??
//?hash???
//redisClient.end(true);??
//redisClient.quit();??
exports.redisClient?=function()?{??
var?redisClient?=?redis.createClient(redis_config);??
var?redisCo?=?wrapper(redisClient);??
return?redisCo;??
};??
exports.redisSave?=function()?{??
return?co(function?*?()?{??
var?redisClient?=?exports.redisClient();??
}).catch(function(error)?{??
log.error('models.redis.order.add('?+?JSON.stringify(order)?+?')',?error);??
return?false;??
????});??
};??
exports.add?=function(order)?{??
return?co(function?*?()?{??
var?result?=?yield?exports.redisSave();??
return?result;??
}).catch(function(error)?{??
log.error('models.redis.order.add('?+?JSON.stringify(order)?+?')',?error);??
return?false;??
??});??
};??