日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

node_redis 中文文档及node_redis 注释笔记(中文版)

發(fā)布時間:2023/12/19 33 生活家
生活随笔 收集整理的這篇文章主要介紹了 node_redis 中文文档及node_redis 注释笔记(中文版) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

node_redis 中文文檔及node_redis 注釋筆記(中文版)

https://github.com/NodeRedis/node_redis

redis - a node.js redis client

這是node.js的一個完整且功能豐富的Redis客戶端。它支持所有的Redis命令,并專注于高性能。

Install with:

npminstallredis

Usage Example

varredis=require("redis"),
client=redis.createClient();

//ifyou'dliketoselectdatabase3,insteadof0(default),call
//client.select(3,function(){/*...*/});

client.on("error",function(err){
console.log("Error"+err);
});

client.set("stringkey","stringval",redis.print);
client.hset("hashkey","hashtest1","somevalue",redis.print);
client.hset(["hashkey","hashtest2","someothervalue"],redis.print);
client.hkeys("hashkey",function(err,replies){
console.log(replies.length+"replies:");
replies.forEach(function(reply,i){
console.log(""+i+":"+reply);
});
client.quit();
});

This will display:

mjr:~/work/node_redis(master)$nodeexample.js
Reply:OK
Reply:0
Reply:0
2replies:
0:hashtest1
1:hashtest2
mjr:~/work/node_redis(master)$

請注意,該API完全是異步的。您需要使用一個回調(diào),從服務(wù)器獲取數(shù)據(jù)。自從2.6版本開始,API支持在所有地方的選項、變量、事件等等使用駝峰和下劃線命名規(guī)范。不過,建議使用Node.js默認(rèn)的風(fēng)格——駝峰式。

--------------------------------------------------

譯者注:

關(guān)于異步我做了一個如下demo

varredis=require("redis"),
client=redis.createClient();

client.set("stringkey",true,()=>{
console.log(1)
});
console.log(2)
client.get("stringkey",(err,key)=>{
console.log(3)
});
console.log(4)

返回了

2
4
1
3

--------------------------------------------------

Promises

你也可以通過如下方式使用bluebird模塊,將node_redispromises化:

varredis=require('redis');
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);

它將在所有node_redis函數(shù)后添加一個Async (例如 return client.getAsync().then())

//Weexpectavalue'foo':'bar'tobepresent
//Soinsteadofwritingclient.get('foo',cb);youhavetowrite:
returnclient.getAsync('foo').then(function(res){
console.log(res);//=>'bar'
});

//Usingmultiwithpromiseslookslike:

returnclient.multi().get('foo').execAsync().then(function(res){
console.log(res);//=>'bar'
});

--------------------------------------------------

譯者注:

bluebird裝飾后可以結(jié)合ES6的await/async使用

varredis=require("redis"),
bluebird=require("bluebird");
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
letclient=redis.createClient();
(asyncfunction(){
awaitclient.setAsync("ip",1,"ex",10);
letip=awaitclient.getAsync("ip");
awaitclient.setAsync("ip",++ip,"ex",10);
ip=awaitclient.getAsync("ip");
console.log(ip)
})();

--------------------------------------------------

Sending Commands

發(fā)送命令

每個Redis命令都作為client對象上的一個函數(shù)暴露出來。所有函數(shù)都采用一個args數(shù)組加上可選的callback函數(shù),或者一個可變數(shù)量的的單獨參數(shù)跟隨一個可選的回調(diào)。例如:

client.hmset(["key","testkeys1","testval1","testkeys2","testval2"],function(err,res){});
//Worksthesameas
client.hmset("key",["testkeys1","testval1","testkeys2","testval2"],function(err,res){});
//Or
client.hmset("key","testkeys1","testval1","testkeys2","testval2",function(err,res){});

Care should be taken with user input if arrays are possible (via body-parser, query string or other method), as single arguments could be unintentionally interpreted as multiple args.

(TODO)

注意,無論哪種形式,回調(diào)都是可選的:

client.set("somekey","someval");client.set(["someotherkey","someval"]);

如果key不存在,將返回null。只有當(dāng)Redis Command Reference特別聲明,它才不會為空。

client.get("missingkey",function(err,reply){//replyisnullwhenthekeyismissing
console.log(reply);
});

Redis命令列表,請參見Redis Command Reference

在返回結(jié)果中進(jìn)行了最低限度的解析。命令中,integer 返回Javascript的Numbers,arrays 返回JavaScript Array.HGETALL返回hash keys作為key的Object .所有strings 將返回 string ,亦或者你特別設(shè)置返回類型為buffer類型 。請注意:null, undefined 和Boolean 在返回中將強(qiáng)制轉(zhuǎn)換為字符串。

--------------------------------------------------

譯者注:

關(guān)于Boolean 在返回中將強(qiáng)制轉(zhuǎn)換為字符串。我做了如下demo

varredis=require("redis"),
client=redis.createClient();

client.set("stringkey",true);
client.get("stringkey",(err,key)=>{
console.log(typeofkey);
});

返回

string

--------------------------------------------------

Redis Commands

Redis命令

這個庫跟Redis命令一一映射。請參照Redis命令頁獲取完整的使用細(xì)節(jié)。

例如使用SET command設(shè)置key值得自動失效時間

//thiskeywillexpireafter10seconds
client.set('key','value!','EX',10);

API

Connection and other Events

客戶端將會發(fā)送一些關(guān)于連接到Redis服務(wù)器的狀態(tài)的事件。

"ready"

client當(dāng)連接建立后,將觸發(fā)一次ready事件. 在ready事件之前發(fā)出的命令將被排隊,ready事件觸發(fā)后,隊列中的命令依次執(zhí)行。

"connect"

一旦stream連接到服務(wù)器,client立即觸發(fā)connect事件。

--------------------------------------------------

譯者注:

關(guān)于“ready“,”connect”執(zhí)行先后問題,設(shè)計了如下demo

varredis=require("redis"),
client=redis.createClient();
client.on("ready",()=>{
console.log("ready");
});
client.on("connect",()=>{
console.log("connect");
});

結(jié)果

connect
ready

--------------------------------------------------

"reconnecting"

在失去連接后,當(dāng)嘗試重新連接到Redis服務(wù)器,client將觸發(fā)reconnecting事件。監(jiān)聽器將被傳遞一個包含delay(in ms) 和attempt(the attempt #) 屬性的對象。

"error"

當(dāng)遇到連接到Redis服務(wù)器錯誤,或在node_redis中出現(xiàn)的任何其他錯誤時,client將觸發(fā)error事件。如果你使用一個沒有回調(diào)的命令,或者遇到返回異常時,錯誤監(jiān)聽器將被觸發(fā)。

因此,請將錯誤偵聽器附加到node_redis上。

"end"

當(dāng)已和Redis服務(wù)器建立的連接被關(guān)閉時,client將觸發(fā)end事件。

"drain" (deprecated棄用)

當(dāng)TCP連接到Redis server曾經(jīng)被緩存,但現(xiàn)在是可寫的(譯者注:緩存池排干時)。這個事件將被用于流命令進(jìn)入Redis,并適應(yīng)背壓。

當(dāng)流被緩存client.should_buffer被設(shè)置為 true. 否則變量始終被設(shè)置為false。這樣你能夠決定何時降低發(fā)送速率,當(dāng)觸發(fā)drain事件時再恢復(fù)傳輸。

您也可以檢查每個命令的返回值,因為它也將返回背壓指示器(不建議使用)。如果返回false,則流必須緩沖。

--------------------------------------------------

譯者注:

關(guān)于drain原理,可以參閱http://taobaofed.org/blog/2015/12/31/nodejs-drain/

我寫了一個drain測試demo

'usestrict';


varredis=require('redis');
varclient=redis.createClient({
return_buffers:true
});
client.auth("g7845120");
varfs=require('fs');
varfilename='Funny-Cat-GIFs.jpg';

fs.readFile(filename,function(err,data){
if(err)throwerr;
console.log('Read'+data.length+'bytesfromfilesystem.');

client.set(filename,data,function(){
console.log("setend")
});//setentirefile
if(client.should_buffer){
client.stream.pause();
}
client.stream.on("drain",function(){
console.log("drain");
client.stream.resume();
});
});

--------------------------------------------------

"warning"

當(dāng)設(shè)置密碼時,但不需要,并且使用了一個不贊成的選項/功能/類似。client將觸發(fā)warning事件。

"idle" (deprecated棄用)

在沒有正在等待響應(yīng)的未完成命令時發(fā)出時,client將觸發(fā)idle事件

redis.createClient()

如果你的node服務(wù)器和redis服務(wù)器運行在同一臺機(jī)器上,那么默認(rèn)設(shè)置的port和host或許是可用的,并且你不需要提供其他參數(shù)。createClient()返回一個RedisClient對象。否則,createClient()需要接受這些參數(shù):

redis.createClient([options])

redis.createClient(unix_socket[, options])

redis.createClient(redis_url[, options])

redis.createClient(port[, host][, options])

提示:如果Redis服務(wù)器與客戶端在同一臺計算機(jī)上運行,請盡可能使用unix套接字來增加吞吐量。

optionsobject properties

Property Default Description
host 127.0.0.1

IP address of the Redis server

port 6379 Port of the Redis server
path null The UNIX socket string of the Redis server
url null The URL of the Redis server. Format:[redis:]//[[user][:password@]][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]](More info avaliable atIANA).
parser javascript DeprecatedUse either the built-in JS parserjavascriptor the nativehiredisparser.Notenode_redis< 2.6 uses hiredis as default if installed. This changed in v.2.6.0.
string_numbers null

設(shè)置為true,node_redis將返回String類型Redis的number值,以替代javascript的Nembers類型。當(dāng)你需要處理一個大數(shù)字時有用(超過Number.MAX_SAFE_INTEGER === 2^53)。Hiredis無能為力,因此設(shè)置此選項true將導(dǎo)致無論parser選項的值如何,都會使用內(nèi)置的JavaScript分析器。

return_buffers false

如果設(shè)置為true,那么所有的返回值將以Buffers的形式替代Strings發(fā)送到回調(diào)函數(shù).

detect_buffers false

如果設(shè)置為true,則返回值將以Buffers發(fā)送到回調(diào)。此選項允許您在每個命令的基礎(chǔ)上在Buffers和字符串之間切換,而return_buffers適用于客戶端上的每個命令。注意:這與pubsub模式無法正常工作。用戶必須總是返回字符串或Buffers。

socket_keepalive true

如果設(shè)置為true,則在底層套接字上啟用keep-alive功能。

no_ready_check false When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server will not respond to any commands. To work around this,node_redishas a "ready check" which sends theINFOcommand to the server. The response from theINFOcommand indicates whether the server is ready for more commands. When ready,node_redisemits areadyevent. Settingno_ready_checktotruewill inhibit this check.
enable_offline_queue true By default, if there is no active connection to the Redis server, commands are added to a queue and are executed once the connection has been established. Settingenable_offline_queuetofalsewill disable this feature and the callback will be executed immediately with an error, or an error will be emitted if no callback is specified.
retry_max_delay null DeprecatedPlease useretry_strategyinstead.By default, every time the client tries to connect and fails, the reconnection delay almost doubles. This delay normally grows infinitely, but settingretry_max_delaylimits it to the maximum value provided in milliseconds.
connect_timeout 3600000 DeprecatedPlease useretry_strategyinstead.Settingconnect_timeoutlimits the total time for the client to connect and reconnect. The value is provided in milliseconds and is counted from the moment a new client is created or from the time the connection is lost. The last retry is going to happen exactly at the timeout time. Default is to try connecting until the default system socket timeout has been exceeded and to try reconnecting until 1h has elapsed.
max_attempts 0 DeprecatedPlease useretry_strategyinstead.By default, a client will try reconnecting until connected. Settingmax_attemptslimits total amount of connection attempts. Setting this to 1 will prevent any reconnect attempt.
retry_unfulfilled_commands false If set totrue, all commands that were unfulfilled while the connection is lost will be retried after the connection has been reestablished. Use this with caution if you use state altering commands (e.g.incr). This is especially useful if you use blocking commands.
password null If set, client will run Redis auth command on connect. Aliasauth_passNotenode_redis< 2.5 must useauth_pass
db null If set, client will run Redisselectcommand on connect.
family IPv4 You can force using IPv6 if you set the family to 'IPv6'. See Node.jsnetordnsmodules on how to use the family type.
disable_resubscribing false If set totrue, a client won't resubscribe after disconnecting.
rename_commands null Passing an object with renamed commands to use instead of the original functions. For example, if you renamed the command KEYS to "DO-NOT-USE" then the rename_commands object would be:{ KEYS : "DO-NOT-USE" }. See theRedis security topicsfor more info.
tls null An object containing options to pass totls.connectto set up a TLS connection to Redis (if, for example, it is set up to be accessible via a tunnel).
prefix null A string used to prefix all used keys (e.g.namespace:test). Please be aware that thekeyscommand will not be prefixed. Thekeyscommand has a "pattern" as argument and no key and it would be impossible to determine the existing keys in Redis if this would be prefixed.
retry_strategy function 這是一個函數(shù),接受一個option對象作為參數(shù),其參數(shù)包含重試attempt,指示距離最后一次連接的時間total_retry_time,為什么連接失敗的error和總共重連次數(shù)的times_connected。如果在這個函數(shù)中你返回一個數(shù)字,那么將在這個數(shù)字的毫秒數(shù)的時間后嘗試重連。如果你返回一個非數(shù)字,則不會再發(fā)生重連,并且所有脫機(jī)命令將會刷新并顯示錯誤。返回一個錯誤,將特定錯誤返回給所有脫機(jī)命令。下面的例子。
varredis=require("redis");
varclient=redis.createClient({detect_buffers:true});

client.set("foo_rand000000000000","OK");

//ThiswillreturnaJavaScriptString
client.get("foo_rand000000000000",function(err,reply){
console.log(reply.toString());//Willprint`OK`
});

//ThiswillreturnaBuffersinceoriginalkeyisspecifiedasaBuffer
client.get(newBuffer("foo_rand000000000000"),function(err,reply){
console.log(reply);//Willprint`<Buffer4f4b>`
//譯者注:官網(wǎng)的代碼是console.log(reply.toString());這會輸出ok而不是`<Buffer4f4b>`
});
client.quit();

retry_strategy example

varclient=redis.createClient({
retry_strategy:function(options){
if(options.error&&options.error.code==='ECONNREFUSED'){
//Endreconnectingonaspecificerrorandflushallcommandswith
//aindividualerror
returnnewError('Theserverrefusedtheconnection');
}
if(options.total_retry_time>1000*60*60){
//Endreconnectingafteraspecifictimeoutandflushallcommands
//withaindividualerror
returnnewError('Retrytimeexhausted');
}
if(options.attempt>10){
//Endreconnectingwithbuiltinerror
returnundefined;
}
//reconnectafter
returnMath.min(options.attempt*100,3000);
}
});

client.auth(password[, callback])

當(dāng)連接的Redis服務(wù)器需要安全認(rèn)證,AUTH命令必須在連接后作為第一條命令被發(fā)送。這可能需要與重新連接、就緒的檢查等進(jìn)行協(xié)調(diào)。為了更方便,client.auth()儲存password ,并在以后的每個連接,包括重連時發(fā)送它。回調(diào)只在對第一個AUTH命令發(fā)出的響應(yīng)之后才調(diào)用一次。注意:你調(diào)用client.auth() 不應(yīng)該在ready事件的處理函數(shù)中。如果你執(zhí)行了這個錯誤,client將觸發(fā)類似這樣的錯誤:Ready check failed: ERR operation not permitted.

--------------------------------------------------

譯者注:

varredis=require("redis")
letclient=redis.createClient();
client.on("ready",()=>{
console.log("ready")
client.auth("g7845120");
});

返回

ReplyError:Readycheckfailed:NOAUTHAuthenticationrequired.

--------------------------------------------------

backpressure

stream

client 在client.stream中暴露使用的stream并且在client.should_buffer中暴露流或者客戶端是否不得不被緩存。結(jié)合這些,你可以通過在發(fā)送一個命令前檢查buffer狀態(tài)并且監(jiān)聽stream的drain事件實現(xiàn)背壓。

client.quit()

這會將退出命令發(fā)送到redis服務(wù)器,并在正確處理所有運行的命令之后以干凈的方式結(jié)束。如果這是在重新連接時調(diào)用的(因此不存在與redis服務(wù)器的連接),它將立即終止連接,而不是產(chǎn)生進(jìn)一步的重新連接!在這種情況下,所有的離線命令都將被一個錯誤所刷新。

client.end(flush)

強(qiáng)行關(guān)閉與Redis服務(wù)器的連接。注意,這不會等到所有的回復(fù)都被解析后才會出現(xiàn)。如果您想要干凈地退出,請調(diào)用上述client.quit()。

如果您不完全確定您不關(guān)心其他命令,那么您應(yīng)該將flush設(shè)置為true。如果您將flush設(shè)置為false,所有仍然運行的命令將會無聲地失敗。

這個例子在讀取回復(fù)之前關(guān)閉了與Redis服務(wù)器的連接。你可能不想這樣做:

varredis=require("redis"),
client=redis.createClient();

client.set("foo_rand000000000000","somefantasticvalue",function(err,reply){
//Thiswilleitherresultinanerror(flushparameterissettotrue)
//orwillsilentlyfailandthiscallbackwillnotbecalledatall(flushsettofalse)
console.log(err);
});
client.end(true);//Nofurthercommandswillbeprocessed
client.get("foo_rand000000000000",function(err,reply){
console.log(err);//=>'Theconnectionhasalreadybeenclosed.'
});

client.end()如果不將flush參數(shù)設(shè)置為true,就不應(yīng)該在生產(chǎn)中使用!

Error handling (>= v.2.6)

當(dāng)前存在以下錯誤子類:

RedisError:客戶端返回的所有錯誤

ReplyErrorRedisError的子類: All errors returned byRedisitself

AbortErrorRedisError的子類: 由于某種原因所有的命令無法完成而中斷

ParserErrorRedisError的子類:返回解析錯誤時返回(這不應(yīng)該發(fā)生)

AggregateErrorRedisError的子類:如果沒有回調(diào)的多個未解決的命令被釋放,在調(diào)試模式中會被rejected,而不是大量的AbortErrors。

所有的錯誤類都是由模塊導(dǎo)出的。

Example:

varredis=require('./');
varassert=require('assert');
varclient=redis.createClient();

client.on('error',function(err){
assert(errinstanceofError);
assert(errinstanceofredis.AbortError);
assert(errinstanceofredis.AggregateError);
//Thesetandgetgetaggregatedinhere
assert.strictEqual(err.errors.length,2);
assert.strictEqual(err.code,'NR_CLOSED');
});
client.set('foo',123,'bar',function(err,res){//Toomanyarguments
assert(errinstanceofredis.ReplyError);//=>true
assert.strictEqual(err.command,'SET');
assert.deepStrictEqual(err.args,['foo',123,'bar']);

redis.debug_mode=true;
client.set('foo','bar');
client.get('foo');
process.nextTick(function(){
//Forceclosingtheconnectionwhilethecommanddidnotyetreturn
client.end(true);
redis.debug_mode=false;
});
});

每個ReplyError都包含有全大寫的command名和參數(shù)(args)。

--------------------------------------------------

譯者注:

varredis=require('redis');
varassert=require('assert');
varclient=redis.createClient();

client.set('foo',123,'bar',function(err,res){//Toomanyarguments
assert(errinstanceofredis.ReplyError);//=>true
console.log(err)
console.log("command:"+err.command);
console.log("args:",err.args);
console.log("code:"+err.code);
});

返回

{ReplyError:ERRsyntaxerror
atparseError(F:	estedis-test
ode_modulesedis-parserlibparser.js:193:12)
atparseType(F:	estedis-test
ode_modulesedis-parserlibparser.js:303:14)command:'SET',args:['foo',123,'bar'],code:'ERR'}
command:SET
args:['foo',123,'bar']
code:ERR

--------------------------------------------------

如果node_redis由于其他錯誤而發(fā)出庫錯誤,則將觸發(fā)錯誤添加到返回的錯誤中,作為origin屬性。

Error codes

如果客戶端連接失敗,noderedis返回一個NR_CLOSED的錯誤代碼。如果一個命令未解決的命令被拒絕,則返回一個UNCERTAIN_STATE的代碼。如果節(jié)點redis放棄了重新連接,則使用一個CONNECTION_BROKEN的錯誤代碼。

--------------------------------------------------

譯者注:

varredis=require('redis');
varassert=require('assert');
varclient=redis.createClient();

client.on('error',function(err){
console.log(err.code)
});
redis.debug_mode=true;
client.set('foo','bar');
process.nextTick(function(){
//Forceclosingtheconnectionwhilethecommanddidnotyetreturn
client.end(true);
redis.debug_mode=false;
});

返回

NR_CLOSED

--------------------------------------------------

client.unref()

在與Redis服務(wù)器的底層套接字連接上調(diào)用unref(),允許程序在不需要更多命令的情況下退出。

這是一個實驗性的特性,并且只支持Redis協(xié)議的一個子集。任何在Redis服務(wù)器上保存客戶端狀態(tài)的命令,例如訂閱或阻塞的BL命令都不能與.unref()一起工作。

varredis=require("redis")
varclient=redis.createClient()

/*
Callingunref()willallowthisprogramtoexitimmediatelyaftertheget
commandfinishes.Otherwisetheclientwouldhangaslongasthe
client-serverconnectionisalive.
調(diào)用unref()將允許該程序在get命令完成之后立即退出
。否則客戶端和服務(wù)器連接將一直保持。
*/
client.unref()
client.get("foo",function(err,value){
if(err)throw(err)
console.log(value)
})

Friendlier hash commands

友好的hash命令

大多數(shù)Redis命令都使用單個字符串或字符串?dāng)?shù)組作為參數(shù),并且返回響應(yīng)單個字符串或字符串?dāng)?shù)組。在處理hash值時,有幾個有用的例外。

client.hgetall(hash, callback)

HGETALL命令的響應(yīng)將會被node_redis轉(zhuǎn)換為JavaScript對象。這樣,你就能夠用JavaScript語法與響應(yīng)進(jìn)行交互了。

Example:

client.hmset("hosts","mjr","1","another","23","home","1234");
client.hgetall("hosts",function(err,obj){
console.dir(obj);
});

Output:

{mjr:'1',another:'23',home:'1234'}

client.hmset(hash, obj[, callback])

Multiple values in a hash can be set by supplying an object:

client.HMSET(key2,{
"0123456789":"abcdefghij",//NOTE:keyandvaluewillbecoercedtostrings
"somemannerofkey":"atypeofvalue"
});

The properties and values of this Object will be set as keys and values in the Redis hash.

client.hmset(hash, key1, val1, ... keyn, valn, [callback])

Multiple values may also be set by supplying a list:

client.HMSET(key1,"0123456789","abcdefghij","somemannerofkey","atypeofvalue");

Publish / Subscribe

發(fā)布/訂閱API的例子。該程序打開兩個客戶端連接,訂閱其中一個通道,并在另一個通道上發(fā)布該通道:

varredis=require("redis");
varsub=redis.createClient(),pub=redis.createClient();
varmsg_count=0;

sub.on("subscribe",function(channel,count){
pub.publish("anicechannel","Iamsendingamessage.");
pub.publish("anicechannel","Iamsendingasecondmessage.");
pub.publish("anicechannel","Iamsendingmylastmessage.");
});

sub.on("message",function(channel,message){
console.log("subchannel"+channel+":"+message);
msg_count+=1;
if(msg_count===3){
sub.unsubscribe();
sub.quit();
pub.quit();
}
});

sub.subscribe("anicechannel");

--------------------------------------------------

譯者注:

varredis=require("redis");
varsub=redis.createClient(),pub=redis.createClient();
varmsg_count=0;

sub.on("subscribe",function(channel,count){
pub.publish("anicechannel","Iamsendingamessage.");
pub.publish("anicechannel","Iamsendingasecondmessage.");
pub.publish("anicechannel","Iamsendingmylastmessage.");
pub.publish("anicechannel","Iamsendingmylastmessage.");//仍會接收
setTimeout(()=>{
pub.publish("anicechannel","Iamsendingmylastmessage.");//將會遺棄
},1000)

});

sub.on("message",function(channel,message){
console.log("subchannel"+channel+":"+message);
msg_count+=1;
if(msg_count===3){
sub.unsubscribe();
sub.quit();
}
});

sub.subscribe("anicechannel");

--------------------------------------------------

當(dāng)客戶機(jī)發(fā)出訂閱或訂閱時,該連接將被放入“訂閱者”模式。在這一點上,只有修改訂閱集的命令是有效的(TODO)。當(dāng)訂閱集為空時,連接將被放回常規(guī)模式。

如果您需要在訂閱模式下向Redis發(fā)送常規(guī)命令,只需打開另一個與新客戶機(jī)的連接(提示:使用client.duplicate())。

Subscriber Events

如果客戶端有訂閱活動,它可能會發(fā)出這些事件:

"message" (channel, message)

客戶端將為收到的每一條與活動的訂閱相匹配的消息發(fā)出message 事件。偵聽器參數(shù)以channel作為頻道名稱,并以message作為消息。

"pmessage" (pattern, channel, message)

客戶端將為收到的每一條與活動訂閱模式相匹配的消息發(fā)出pmessage事件。偵聽器參數(shù)以PSUBSCRIBE作為原始的正則匹配模式 、以channel作為頻道名稱,并以message作為消息。

--------------------------------------------------

譯者注:

源碼中查找demo如下

'usestrict';

varredis=require('redis');
varclient1=redis.createClient();
varclient2=redis.createClient();
varclient3=redis.createClient();
varclient4=redis.createClient();
varmsg_count=0;

client1.on('psubscribe',function(pattern,count){
console.log('client1psubscribedto'+pattern+','+count+'totalsubscriptions');
client2.publish('channeltwo','Me!');
client3.publish('channelthree','Metoo!');
client4.publish('channelfour','Andmetoo!');
});

client1.on('punsubscribe',function(pattern,count){
console.log('client1punsubscribedfrom'+pattern+','+count+'totalsubscriptions');
client4.end();
client3.end();
client2.end();
client1.end();
});

client1.on('pmessage',function(pattern,channel,message){
console.log('('+pattern+')client1receivedmessageon'+channel+':'+message);
msg_count+=1;
if(msg_count===3){
client1.punsubscribe();
}
});

client1.psubscribe('channel*');

由于channel*正則匹配了channeltwo、channelthree、channelfour。client1就能接收到這三個頻道的消息。

--------------------------------------------------

"message_buffer" (channel, message)

This is the same as themessageevent with the exception, that it is always going to emit a buffer. If you listen to themessageevent at the same time as themessage_buffer, it is always going to emit a string.

(TODO)

"pmessage_buffer" (pattern, channel, message)

This is the same as thepmessageevent with the exception, that it is always going to emit a buffer. If you listen to thepmessageevent at the same time as thepmessage_buffer, it is always going to emit a string.

(TODO)

"subscribe" (channel, count)

客戶端根據(jù)SUBSCRIBE命令觸發(fā)subscribe事件。偵聽器參數(shù)以channel作為頻道名稱,并以count作為新訂閱者數(shù)量。

"psubscribe" (pattern, count)

客戶端根據(jù)PSUBSCRIBE命令觸發(fā)psubscribe事件。偵聽器參數(shù)以pattern作為原始的正則匹配模式,并以count作為新訂閱者數(shù)量。

"unsubscribe" (channel, count)

客戶端根據(jù)UNSUBSCRIBE命令觸發(fā)unsubscribe事件。偵聽器參數(shù)以channel作為頻道名稱,并以count作為新訂閱者數(shù)量。當(dāng)count為0時,客戶端將退出訂閱者模式,并且不再有訂閱者事件觸發(fā)。

"punsubscribe" (pattern, count)

客戶端根據(jù)PUNSUBSCRIBE命令觸發(fā)punsubscribe事件。偵聽器參數(shù)以pattern作為原始的正則匹配模式,并以count作為新訂閱者數(shù)量。當(dāng)count為0時,客戶端將退出訂閱者模式,并且不再有訂閱者事件觸發(fā)。

client.multi([commands])

MULTI命令排隊直到一個EXEC 命令被執(zhí)行,然后所有的命令都由Redis原子運行。node_redis的接口是通過調(diào)用client.multi()返回一個單獨的Multi對象。如果隊列中任何命令執(zhí)行失敗,那么所有命令都會被回滾,并且不會執(zhí)行任何操作(更多信息查看transactions)。

varredis=require("./index"),
client=redis.createClient(),set_size=20;

client.sadd("bigset","amember");
client.sadd("bigset","anothermember");

while(set_size>0){
client.sadd("bigset","member"+set_size);
set_size-=1;
}

//multichainwithanindividualcallback
client.multi()
.scard("bigset")
.smembers("bigset")
.keys("*",function(err,replies){
//NOTE:codeinthiscallbackisNOTatomic
//thisonlyhappensafterthethe.execcallfinishes.
client.mget(replies,redis.print);
})
.dbsize()
.exec(function(err,replies){
console.log("MULTIgot"+replies.length+"replies");
replies.forEach(function(reply,index){
console.log("Reply"+index+":"+reply.toString());
});
});

Multi.exec([callback])

client.multi()是一個返回Multi對象的構(gòu)造函數(shù)。Multi對象與client對象共享所有相同的命令方法。在multi對象中,直到multi.exec()被調(diào)用,命令才被調(diào)用。

如果您的代碼包含一個語法錯誤,那么將會拋出一個EXECABORT 錯誤,所有的命令都將被中止。那個錯誤包含一個.errors屬性以描述具體的錯誤。如果所有命令都成功地排隊,并且并且一個錯誤在redis執(zhí)行命令的過程中被拋出,那么錯誤將在結(jié)果數(shù)組中被返回!除了onces失敗之外,其他命令不會被中止。

您可以像上面的示例中將多個命令鏈接,或者您仍然可以如以下例子那樣,排列并發(fā)送單條普通命令,

varredis=require("redis"),
client=redis.createClient(),multi;

//startaseparatemulticommandqueue
multi=client.multi();
multi.incr("incrthing",redis.print);
multi.incr("incrotherthing",redis.print);

//runsimmediately
client.mset("incrthing",100,"incrotherthing",1,redis.print);

//drainsmultiqueueandrunsatomically
multi.exec(function(err,replies){
console.log(replies);//101,2
});

除了向多隊列添加命令之外,還可以向構(gòu)造函數(shù)傳遞一個命令和參數(shù)數(shù)組:

varredis=require("redis"),
client=redis.createClient();

client.multi([
["mget","multifoo","multibar",redis.print],
["incr","multifoo"],
["incr","multibar"]
]).exec(function(err,replies){
console.log(replies);
});

Multi.exec_atomic([callback])

與Multi.exec類似,但是區(qū)別是執(zhí)行單個命令時不會使用事務(wù)。

client.batch([commands])

與 .multi 相同但沒有事務(wù)。如果您希望同時執(zhí)行多個命令,但不需要依賴事務(wù),那么建議您這樣做。

BATCH批處理命令在隊列中排隊等待執(zhí)行,然后所有的命令都由Redis原子運行。node_redis中的接口是通過調(diào)用client.Batch()來返回一個單獨的Batch處理對象。.batch和.multi的唯一區(qū)別是.batch沒有事務(wù)。注意,錯誤-就像在multi語句中一樣-返回在結(jié)果中。否則,錯誤和結(jié)果都可以同時返回。

如果您同時觸發(fā)多個命令,那么這與一個循環(huán)中執(zhí)行相同的命令相比將大大提高執(zhí)行速度,而不需要等待結(jié)果!查看benchmarks 獲取更多比較信息。請記住,所有的命令都保存在內(nèi)存中,直到它們被觸發(fā)。

Monitor mode

Redis支持MONITOR命令,它讓您可以看到所有客戶端連接的所有命令,包括來自其他客戶端庫和其他計算機(jī)。

對于連接到服務(wù)器的任何客戶端發(fā)出的每個命令,都會發(fā)出一個monitor事件,包括monitoring客戶端本身。monitor事件的回調(diào)從Redis服務(wù)器獲取時間戳,一個命令參數(shù)數(shù)組和原始監(jiān)控字符串。

Example:

varclient=require("redis").createClient();
client.monitor(function(err,res){
console.log("Enteringmonitoringmode.");
});
client.set('foo','bar');

client.on("monitor",function(time,args,raw_reply){
console.log(time+":"+args);//1458910076.446514:['set','foo','bar']
});

Extras

還有一些你可能想知道的事情。

client.server_info

在就緒的探測完成之后,INFO命令的結(jié)果將保存在client.server_info對象中。

versions鍵包含以版本字符串的字符組成的數(shù)組中,以便進(jìn)行比較。

>client.server_info.redis_version
'2.3.0'
>client.server_info.versions
[2,3,0]

redis.print()

一個方便的回調(diào)函數(shù),用于在測試時顯示返回值。例子:

varredis=require("redis"),
client=redis.createClient();

client.on("connect",function(){
client.set("foo_rand000000000000","somefantasticvalue",redis.print);
client.get("foo_rand000000000000",redis.print);
});

This will print:

Reply:OK
Reply:somefantasticvalue

注意,這個程序不會干凈地退出,因為客戶端仍然是連接的。

Multi-word commands

執(zhí)行redis的multi-word命令,如SCRIPT LOAD或CLIENT LIST,將第二個單詞作為第一個參數(shù)傳遞:

client.script('load','return1');
client.multi().script('load','return1').exec(...);
client.multi([['script','load','return1']]).exec(...);

client.duplicate([options][, callback])

復(fù)制所有當(dāng)前選項并返回一個新的redisClient實例。傳遞給duplicate函數(shù)的所有選項都將替換原來的選項。如果您傳遞一個回調(diào),duplicate將等待客戶端準(zhǔn)備好并在回調(diào)中返回它。如果與此同時發(fā)生錯誤,則會返回一個錯誤,而不是在回調(diào)中。

使用duplicate()的一個例子包含如下連接——阻塞的redis命令BRPOP、BLPOP和BRPOPLPUSH。如果這些命令在與非阻塞命令相同的redisClient實例上使用,則非阻塞的命令可能會排隊直到阻塞的命令結(jié)束。

varRedis=require('redis');
varclient=Redis.createClient();
varclientBlocking=client.duplicate();

varget=function(){
console.log("getcalled");
client.get("any_key",function(){console.log("getreturned");});
setTimeout(get,1000);
};
varbrpop=function(){
console.log("brpopcalled");
clientBlocking.brpop("nonexistent",5,function(){
console.log("brpopreturn");
setTimeout(brpop,1000);
});
};
get();
brpop();

使用duplicate()的另一個原因是,通過redis SELECT命令訪問同一個服務(wù)器上的多個DBs。每個DB都可以使用它自己的連接。

client.send_command(command_name[, [args][, callback]])

所有的Redis命令都被添加到客戶端對象中。但是,如果在這個庫更新之前引入了新的命令,或者如果您想要添加單獨的命令,那么可以使用sendcommand()向Redis發(fā)送任意命令。

所有命令都是作為多批量命令發(fā)送的。args可以是一組參數(shù),也可以是未定義的參數(shù)。

client.add_command(command_name)

調(diào)用add_command將向原型添加一個新的命令。在使用這個新命令調(diào)用時,將使用精確的命令名。使用任意參數(shù)與任何其他命令一樣是可能的。

client.connected

跟蹤連接到Redis服務(wù)器的連接狀態(tài)的布爾值。

client.command_queue_length

The number of commands that have been sent to the Redis server but not yet replied to. You can use this to enforce some kind of maximum queue depth for commands while connected.

client.offline_queue_length

已經(jīng)發(fā)送到Redis服務(wù)器但還沒有回復(fù)的命令數(shù)量。你可以使用這條命令為pre-connection命令去執(zhí)行一些類別的最大隊列深度。

Commands with Optional and Keyword arguments

這適用于任何使用一個可選的在redis.io/commands文檔中的[WITHSCORES]或[LIMIT offset count]。

Example:

varargs=['myzset',1,'one',2,'two',3,'three',99,'ninety-nine'];
client.zadd(args,function(err,response){
if(err)throwerr;
console.log('added'+response+'items.');

//-Infinityand+Infinityalsowork
varargs1=['myzset','+inf','-inf'];
client.zrevrangebyscore(args1,function(err,response){
if(err)throwerr;
console.log('example1',response);
//writeyourcodehere
});

varmax=3,min=1,offset=1,count=2;
varargs2=['myzset',max,min,'WITHSCORES','LIMIT',offset,count];
client.zrevrangebyscore(args2,function(err,response){
if(err)throwerr;
console.log('example2',response);
//writeyourcodehere
});
});

Performance

為了使node_redis盡可能快地進(jìn)行普通操作,花費了大量的精力。

LenovoT450s,i7-5600Uand12gbmemory
clients:1,NodeJS:6.2.0,Redis:3.2.0,parser:javascript,connectedby:tcp
PING,1/1avg/max:0.02/5.262501mstotal,46916ops/sec
PING,batch50/1avg/max:0.06/4.352501mstotal,755178ops/sec
SET4Bstr,1/1avg/max:0.02/4.752501mstotal,40856ops/sec
SET4Bstr,batch50/1avg/max:0.11/1.512501mstotal,432727ops/sec
SET4Bbuf,1/1avg/max:0.05/2.762501mstotal,20659ops/sec
SET4Bbuf,batch50/1avg/max:0.25/1.762501mstotal,194962ops/sec
GET4Bstr,1/1avg/max:0.02/1.552501mstotal,45156ops/sec
GET4Bstr,batch50/1avg/max:0.09/3.152501mstotal,524110ops/sec
GET4Bbuf,1/1avg/max:0.02/3.072501mstotal,44563ops/sec
GET4Bbuf,batch50/1avg/max:0.10/3.182501mstotal,473171ops/sec
SET4KiBstr,1/1avg/max:0.03/1.542501mstotal,32627ops/sec
SET4KiBstr,batch50/1avg/max:0.34/1.892501mstotal,146861ops/sec
SET4KiBbuf,1/1avg/max:0.05/2.852501mstotal,20688ops/sec
SET4KiBbuf,batch50/1avg/max:0.36/1.832501mstotal,138165ops/sec
GET4KiBstr,1/1avg/max:0.02/1.372501mstotal,39389ops/sec
GET4KiBstr,batch50/1avg/max:0.24/1.812501mstotal,208157ops/sec
GET4KiBbuf,1/1avg/max:0.02/2.632501mstotal,39918ops/sec
GET4KiBbuf,batch50/1avg/max:0.31/8.562501mstotal,161575ops/sec
INCR,1/1avg/max:0.02/4.692501mstotal,45685ops/sec
INCR,batch50/1avg/max:0.09/3.062501mstotal,539964ops/sec
LPUSH,1/1avg/max:0.02/3.042501mstotal,41253ops/sec
LPUSH,batch50/1avg/max:0.12/1.942501mstotal,425090ops/sec
LRANGE10,1/1avg/max:0.02/2.282501mstotal,39850ops/sec
LRANGE10,batch50/1avg/max:0.25/1.852501mstotal,194302ops/sec
LRANGE100,1/1avg/max:0.05/2.932501mstotal,21026ops/sec
LRANGE100,batch50/1avg/max:1.52/2.892501mstotal,32767ops/sec
SET4MiBstr,1/1avg/max:5.16/15.552502mstotal,193ops/sec
SET4MiBstr,batch20/1avg/max:89.73/99.962513mstotal,223ops/sec
SET4MiBbuf,1/1avg/max:2.23/8.352501mstotal,446ops/sec
SET4MiBbuf,batch20/1avg/max:41.47/50.912530mstotal,482ops/sec
GET4MiBstr,1/1avg/max:2.79/10.912502mstotal,358ops/sec
GET4MiBstr,batch20/1avg/max:101.61/118.112541mstotal,197ops/sec
GET4MiBbuf,1/1avg/max:2.32/14.932502mstotal,430ops/sec
GET4MiBbuf,batch20/1avg/max:65.01/84.722536mstotal,308ops/sec

Debugging

為了獲得調(diào)試輸出,您可以在node_redis應(yīng)用程序中使用NODE_DEBUG=redis。

這也會導(dǎo)致好的堆棧跟蹤,而不是無用的堆棧跟蹤,否則對于任何異步操作都是如此。如果您只想擁有好的堆棧跟蹤,而不是調(diào)試輸出,請在開發(fā)模式中運行您的應(yīng)用程序(NODE_ENV=development)。

好的堆棧跟蹤只在開發(fā)和調(diào)試模式中被激活,因為這將導(dǎo)致嚴(yán)重的性能損失。

Comparison: Useless stack trace:

ReplyError:ERRwrongnumberofargumentsfor'set'command
atparseError(/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:158:12)
atparseType(/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:219:14)

Good stack trace:

ReplyError:ERRwrongnumberofargumentsfor'set'command
atnewCommand(/home/ruben/repos/redis/lib/command.js:9:902)
atRedisClient.set(/home/ruben/repos/redis/lib/commands.js:9:3238)
atContext.<anonymous>(/home/ruben/repos/redis/test/good_stacks.spec.js:20:20)
atcallFnAsync(/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:349:8)
atTest.Runnable.run(/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:301:7)
atRunner.runTest(/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:422:10)
at/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:528:12
atnext(/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:342:14)
at/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:352:7
atnext(/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:284:14)
atImmediate._onImmediate(/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:320:5)
atprocessImmediate[as_immediateCallback](timers.js:383:17)

How to Contribute

Open a pull request or an issue about what you want to implement / change. We're glad for any help!

Please be aware that we'll only accept fully tested code.

Contributors

The original author of node_redis isMatthew Ranney

The current lead maintainer isRuben Bridgewater

Manyotherscontributed tonode_redistoo. Thanks to all of them!

License

MIT

Consolidation: It's time for celebration

Right now there are two great redis clients around and both have some advantages above each other. We speak about ioredis and node_redis. So after talking to each other about how we could improve in working together we (that is @luin and @BridgeAR) decided to work towards a single library on the long run. But step by step.

First of all, we want to split small parts of our libraries into others so that we're both able to use the same code. Those libraries are going to be maintained under the NodeRedis organization. This is going to reduce the maintenance overhead, allows others to use the very same code, if they need it and it's way easyer for others to contribute to both libraries.

We're very happy about this step towards working together as we both want to give you the best redis experience possible.

If you want to join our cause by help maintaining something, please don't hesitate to contact either one of us.

總結(jié)

以上是生活随笔為你收集整理的node_redis 中文文档及node_redis 注释笔记(中文版)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。