Nodejs學習筆記(九)--- 與Redis的交互(mranney/node_redis)入門

目錄

簡介和安裝

  • redis簡介:
  1. 開源高性能key-value存儲;採用內存中(in-memory)數據集的方式,也可以採用磁盤存儲方式(前者性能高,但數據可能丟失,後者正好相反)
  2. 支持字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等;支持對複雜數據結構的高速操作。
  3. 特性多,支持主從同步、pub/sub等
  4. 支持多種客戶端(http://redis.io/clients
  5. ...

  注:應用場景沒有提到,暫時沒有太多實際體會,不瞎說,以免誤導人,但是從它的簡介和特性來說,起碼緩存場景是不錯的!

  Redis下載地址: https://github.com/dmajkic/redis/downloads  

  node.js客戶端:node_redis https://github.com/mranney/node_redis/

  • redis安裝(Windows平臺)

   redis非常方便,直接下載解壓就可以使用,因爲開發環境是win7 64位,直接下載(示例下載的安裝包:redis-2.4.5-win32-win64.zip)

  • redis運行

  解壓到後運行"64bit"文件夾下的redis-server.exe即可,但是這樣運行會出現一個如下警告提示:

  #Warning: no config file specified,using the default config. In order to specify a config file use ‘redis-server /path/to/redis.conf’

  提示也比較明顯,沒有明確的配置文件,使用的是默認配置,請使用‘redis-server /path/to/redis.conf’指定明確的配置文件

   根據提示運行redis成功(如下圖)

  在redis-server.exe同級目錄下可以看到一個redis.conf文件,這就是配置文件

  • node_redis安裝
npm install redis
或者
npm install hiredis redis

  我這裏採用 npm install hiredis redis 安裝

  注:兩種都可用,區別在於性能,hiredis是非阻塞的,而且速度更快;如果安裝了hiredis,node_redis則會默認以它爲解析器,沒安裝就會用純javascript解釋器,對於學習或者開發環境,用哪個都無所謂

redis.createClient()連接到redis服務器

  環境都準備好了,就開始寫一代簡單的代碼測試用nodejs連接一下服務器

var redis = require('redis'),
    client = redis.createClient();

client.on('ready',function(err){
    console.log('ready');
});
示例源碼

  從上圖中可以看到運行結果,輸出ready,表示成功!  

  對代碼還是講一下:

  redis.createClient():返回的是一個RedisClient的對象,大家可以輸出來看一下此對象的具體信息。

  ready:Redis的Connection事件之一,當與redis服務器連接成功後會觸發這個事件,此時表示已經準備好接收命令,當這個事件觸發之前client命令會存在隊列中,當一切準備就緒後按順序調用

 

  對於上面的幾句代碼就能連接成功redis服務器,原因是當前redis服務器在本地,如果不在本地,怎麼連接呢?

var redis = require('redis'),
    RDS_PORT = 6379,        //端口號
    RDS_HOST = '127.0.1.1',    //服務器IP
    RDS_OPTS = {},            //設置項
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.on('ready',function(res){
    console.log('ready');    
});
示例源碼

  也是成功!這種方式和上一種在redis.createClient()時分別傳入了端口號、服務器IP和設置項

  這樣就可以用於連接遠程的redis服務器,或者利用第三個參數進行一些配置!

  redis的默認端口:6379

認證 client.auth(password, callback)

  上面試過了,連接到redis服務器,可以看出我們並沒有輸入密碼進行驗證的過程就成功連接到了服務器,因爲redis服務器默認不需要密碼,不過這不太安全,我們肯定要設置一下密碼

  打開redis.conf文件,找到requirepass,取消註釋,設置密碼爲:porschev

requirepass porschev

  然後重啓redis服務器;再次利用上面的代碼連接到redis服務器,出現錯誤提示(如下圖):ERR operation not permitted

  那麼如何連接到有密碼的redis服務器呢?

  簡單的試了一下,有兩種方法(可能有更多,沒試,其實一種完全就夠了,多了也沒用^_^!)

  方式一:通過設置redis.createClient()的第三個參數,也就是設置項來完成

 

var redis = require('redis'),
    RDS_PORT = 6379,        //端口號
    RDS_HOST = '127.0.1.1',    //服務器IP
    RDS_PWD = 'porschev',
    RDS_OPTS = {auth_pass:RDS_PWD},            //設置項
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.on('ready',function(res){
    console.log('ready');    
});
示例源碼

  上圖可以連接成功,通過設置連接設置項中的auth_pass來通過認證!

  auth_pass:默認值爲null,默認情況下客戶端將不通過auth命令連接,如果設置了此項,客戶端將調用auth命令連接

  方式二:通過client.auth(password, callback)

var redis = require('redis'),
    RDS_PORT = 6379,        //端口號
    RDS_HOST = '127.0.1.1',    //服務器IP
    RDS_PWD = 'porschev',
    RDS_OPTS = {},            //設置項
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.auth(RDS_PWD,function(){
    console.log('通過認證');
});

client.on('ready',function(res){
    console.log('ready');    
});
示例源碼

  此方法也可以成功,第一個參數爲密碼,第二個爲回調函數!

單值set和get

var redis = require('redis'),
    RDS_PORT = 6379,        //端口號
    RDS_HOST = '127.0.1.1',    //服務器IP
    RDS_PWD = 'porschev',    //密碼    
    RDS_OPTS = {},            //設置項
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.auth(RDS_PWD,function(){
    console.log('通過認證');
});

client.on('connect',function(){
    client.set('author', 'Wilson',redis.print);
    client.get('author', redis.print);
    console.log('connect');
});

client.on('ready',function(err){
    console.log('ready');
});
示例源碼

  從輸出結果可以看出,set一個值和獲取這個值都成功!

  代碼講一下:

  client.set(key,value,[callback]):設置單個key和value,回調函數可選

  client.get(key,[callback]):得到key得到value,回調函數可選(雖然可選,但不寫回調函數獲取又有什麼意義呢^_^!)

  connect:Redis的Connection事件之一,在不設置client.options.no_ready_check的情況下,客戶端觸發connect同時它會發出ready,如果設置了client.options.no_ready_check,當這個stream被連接時會觸發connect,

          這時候就可以自由嘗試發命令

  redis.print:簡便的回調函數,測試時顯示返回值(從示例的輸出結果中可以看出)

 

  其它補充說明:

      client.options.no_ready_check:默認值爲false,當連接到一臺redis服務器時,服務器也許正在從磁盤中加載數據庫,當正在加載階段,redis服務器不會響應任何命令,node_redis會發送一個“準備確認”的INFO命令,

                 INFO命令得到響應表示此時服務器可以提供服務,這時node_redis會觸發"ready"事件,如果該設置項設置爲true,則不會有這種檢查

  client.set([key,value],callback):與client.set(key,value,[callback]);效果一致(可以自行對上面示例源碼進行修改進行測試),必須要有回調函數

多值get和set

var redis = require('redis'),
    RDS_PORT = 6379,        //端口號
    RDS_HOST = '127.0.1.1',    //服務器IP
    RDS_PWD = 'porschev',    //密碼    
    RDS_OPTS = {},            //設置項
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.auth(RDS_PWD,function(){
    console.log('通過認證');
});

client.on('connect',function(){
    client.hmset('short', {'js':'javascript','C#':'C Sharp'}, redis.print);
    client.hmset('short', 'SQL','Structured Query Language','HTML','HyperText Mark-up Language', redis.print);

    client.hgetall("short", function(err,res){
        if(err)
        {
            console.log('Error:'+ err);
            return;
        }            
        console.dir(res);
    });
});

client.on('ready',function(err){
    console.log('ready');
});
示例源碼

  從輸出結果可以看出,set多值和獲取都成功!

  代碼講一下:

  client.hmset(hash, obj, [callback]):賦值操作,第一個參數是hash名稱;第二個參數是object對象,其中key1:value1。。,keyn:valuen形式;第三個參數是可選回調函數

  client.hmset(hash, key1, val1, ... keyn, valn, [callback]):與上面做用一致,第2個參數到可選回調函數之前的參數都是key1, val1, ... keyn, valn形式;

  client.hgetall(hash, [callback]):獲取值操作,返回一個對象

 

  其它補充說明:

  console.dir()用於顯示一個對象所有的屬性和方法

打包執行多個命令[事務]

var redis = require('redis'),
    RDS_PORT = 6379,        //端口號
    RDS_HOST = '127.0.1.1',    //服務器IP
    RDS_PWD = 'porschev',    //密碼    
    RDS_OPTS = {},            //設置項
    client = redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);

client.auth(RDS_PWD,function(){
    console.log('通過認證');
});

client.on('end',function(err){
    console.log('end');
});

client.on('connect',function(){
    var key = 'skills';
      client.sadd(key, 'C#','java',redis.print);
      client.sadd(key, 'nodejs');
      client.sadd(key, "MySQL");
      
      client.multi()      
      .sismember(key,'C#')
      .smembers(key)
      .exec(function (err, replies) {
            console.log("MULTI got " + replies.length + " replies");
            replies.forEach(function (reply, index) {
                console.log("Reply " + index + ": " + reply.toString());
            });
            client.quit();
    });
});
示例源碼

  官方有個示例,我修改一下,可能更好理解一些,下面一步步說吧!

    先了解一下API再看結果

  client.multi([commands]):這個標記一個事務的開始,由Multi.exec原子性的執行;github上描述是可以理解爲打包,把要執行的命令存放在隊列中,redis服務器會原子性的執行所有命令,node_redis接口返回一個Multi對象

  Multi.exec( callback ):執行事務內所有命令;github上描述是client.multi()返回一個Multi對象,它包含了所有命令,直到Multi.exec()被調用;

  Multi.exec( callback )回調函數參數err:返回null或者Array,出錯則返回對應命令序列鏈中發生錯誤的錯誤信息,這個數組中最後一個元素是源自exec本身的一個EXECABORT類型的錯誤

  Multi.exec( callback )回調函數參數results返回null或者Array,返回命令鏈中每個命令的返回信息

  end:redis已建立的連接被關閉時觸發

  client.sadd(key,value1,...valuen,[callback]):集合操作,向集合key中添加N個元素,已存在元素的將忽略;redis2.4版本前只能添加一個值

  sismember(key,value,[callback]):元素value是否存在於集合key中,存在返回1,不存在返回0

  smembers(key,[callback]):返回集合 key 中的所有成員,不存在的集合key也不會報錯,而是當作空集返回

  client.quit():與之對應的還有一個client.end()方法,相對比較暴力;client.quit方法會接收到所有響應後發送quit命令,而client.end則是直接關閉;都是觸發end事件

 

  再看結果應該就比較簡單了,client.multi打包了sismember和smembers兩個命令,執行exec方法後,回調函數得到兩個迴應,分別輸出兩個迴應的結果!

其它...

  redis.debug_mode:這個在開發中可能有用,大家自行設置試一下,設置爲true後,看輸出

  Publish / Subscribe:這個官方示例比較簡單清晰,大家運行起來看一下就能理解,深入的網上還有很多用它實現的聊天、監控示例,大家看一下,如果以後覺得有必要就再做個示例分享一下

  client.monitor:監控,可能以後會用到,有需要的深入研究一下,入門可以略過

 

  其它redis命令還有不少,能講到的非常有限,深入練習可以對照:http://redis.readthedocs.org/en/latest/index.html

 

  參數資料:

  https://github.com/mranney/node_redis/

  http://redis.readthedocs.org/en/latest/index.html

  http://dumbee.net/archives/114

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章