Linux下安裝redis 2.6.14及C語言中客戶端實現demo

http://changfengmingzhi.blog.163.com/blog/static/16710528820142755922558/ php


一、獲取安裝文件html

wget http://download.redis.io/redis-stable.tar.gzjava

或者手動下載:https://code.google.com/p/redis/downloads/detail?name=redis-2.6.14.tar.gz&can=2&q=python

二、解壓文件git

tar xzvf redis-stable.tar.gzgithub

三、進入目錄web

cd redis-stableredis

四、編譯算法

make數據庫

五、安裝

make install

六、設置配置文件路徑

mkdir -p /etc/redis

cp redis.conf /etc/redis

七、修改配置文件

vi /etc/redis/redis.conf

僅修改: daemonize yes 

八、啓動

/usr/local/bin/redis-server /etc/redis/redis.conf

九、將Redis做爲 Linux 服務隨機啓動

vim /etc/rc.local, 使用vi編輯器打開隨機啓動配置文件,並在其中加入下面一行代碼。

/home/xxxx/redis-2.2.12/src/redis-server

九、查看啓動

ps -ef | grep redis  

十、使用客戶端

redis-cli

>set name david

OK

>get name

"david"

11.中止Redis實例

最簡單的方法是在啓動實例的session中,直接使用Control-C來將實例中止。

咱們還能夠用客戶端來中止服務,如能夠用shutdown來中止Redis實例, 具體以下:

[root@localhost redis-2.2.12]# src/redis-cli shutdown

12.如何配置Redis

源碼編譯完成後,在redis-2.2.12目錄下有一個redis.conf文件,這個文件便是Redis的配置文件

Redis支持不少的參數,但都有默認值。

  ●daemonize:

  默認狀況下,redis不是在後臺運行的,若是須要在後臺運行,把該項的值更改成yes。

  ●pidfile

  當Redis在後臺運行的時候,Redis默認會把pid文件放在/var/run/redis.pid,你能夠配置到其餘地址。當運行多個redis服務時,須要指定不一樣的pid文件和端口。

  ●bind

  指定Redis只接收來自於該IP地址的請求,若是不進行設置,那麼將處理全部請求,在生產環境中最好設置該項。

  ●port

  監聽端口,默認爲6379。

  ●timeout

  設置客戶端鏈接時的超時時間,單位爲秒。當客戶端在這段時間內沒有發出任何指令,那麼關閉該鏈接。

  ●loglevel

  log等級分爲4級,debug, verbose, notice, 和warning。生產環境下通常開啓notice。

  ●logfile

  配置log文件地址,默認使用標準輸出,即打印在命令行終端的窗口上。

  ●databases

  設置數據庫的個數,可使用SELECT 命令來切換數據庫。默認使用的數據庫是0。

  ●save

  設置Redis進行數據庫鏡像的頻率。

  if(在60秒以內有10000個keys發生變化時){

  進行鏡像備份

  }else if(在300秒以內有10個keys發生了變化){

  進行鏡像備份

  }else if(在900秒以內有1個keys發生了變化){

  進行鏡像備份

  }


  ●rdbcompression

  在進行鏡像備份時,是否進行壓縮。

  ●dbfilename

  鏡像備份文件的文件名。

  ●dir

  數據庫鏡像備份的文件放置的路徑。這裏的路徑跟文件名要分開配置是由於Redis在進行備份時,先會將當前數據庫的狀態寫入到一個臨時文件中,等備份完成時,再把該該臨時文件替換爲上面所指定的文件,而這裏的臨時文件和上面所配置的備份文件都會放在這個指定的路徑當中。

  ●slaveof

  設置該數據庫爲其餘數據庫的從數據庫。

  ●masterauth

  當主數據庫鏈接須要密碼驗證時,在這裏指定。

  ●requirepass

  設置客戶端鏈接後進行任何其餘指定前須要使用的密碼。警告:由於redis速度至關快,因此在一臺比較好的服務器下,一個外部的用戶能夠在一秒鐘進行150K次的密碼嘗試,這意味着你須要指定很是很是強大的密碼來防止暴力破解。

  ●maxclients

  限制同時鏈接的客戶數量。當鏈接數超過這個值時,redis將再也不接收其餘鏈接請求,客戶端嘗試鏈接時將收到error信息。

  ●maxmemory

  設置redis可以使用的最大內存。當內存滿了的時候,若是還接收到set命令,redis將先嚐試剔除設置過expire信息的key,而無論該key的過時時間尚未到達。在刪除時,將按照過時時間進行刪除,最先將要被過時的key將最早被刪除。若是帶有expire信息的key都刪光了,那麼將返回錯誤。這樣,redis將再也不接收寫請求,只接收get請求。maxmemory的設置比較適合於把redis看成於相似memcached的緩存來使用。

  ●appendonly

  默認狀況下,redis會在後臺異步的把數據庫鏡像備份到磁盤,可是該備份是很是耗時的,並且備份也不能很頻繁,若是發生諸如拉閘限電、拔插頭等情況,那麼將形成比較大範圍的數據丟失。因此redis提供了另一種更加高效的數據庫備份及災難恢復方式。開啓append only模式以後,redis會把所接收到的每一次寫操做請求都追加到appendonly.aof文件中,當redis從新啓動時,會從該文件恢復出以前的狀態。可是這樣會形成appendonly.aof文件過大,因此redis還支持了BGREWRITEAOF指令,對appendonly.aof進行從新整理。因此我認爲推薦生產環境下的作法爲關閉鏡像,開啓appendonly.aof,同時能夠選擇在訪問較少的時間天天對appendonly.aof進行重寫一次。

  ●appendfsync

  設置對appendonly.aof文件進行同步的頻率。always表示每次有寫操做都進行同步,everysec表示對寫操做進行累積,每秒同步一次。這個須要根據實際業務場景進行配置。

  ●vm-enabled

  是否開啓虛擬內存支持。由於redis是一個內存數據庫,並且當內存滿的時候,沒法接收新的寫請求,因此在redis 2.0中,提供了虛擬內存的支持。可是須要注意的是,redis中,全部的key都會放在內存中,在內存不夠時,只會把value值放入交換區。這樣保證了雖然使用虛擬內存,但性能基本不受影響,同時,你須要注意的是你要把vm-max-memory設置到足夠來放下你的全部的key。

  ●vm-swap-file

  設置虛擬內存的交換文件路徑。

  ●vm-max-memory

  這裏設置開啓虛擬內存以後,redis將使用的最大物理內存的大小。默認爲0,redis將把他全部的能放到交換文件的都放到交換文件中,以儘可能少的使用物理內存。在生產環境下,須要根據實際狀況設置該值,最好不要使用默認的0。

  ●vm-page-size

  設置虛擬內存的頁大小,若是你的value值比較大,好比說你要在value中放置博客、新聞之類的全部文章內容,就設大一點,若是要放置的都是很小的內容,那就設小一點。

  ●vm-pages

  設置交換文件的總的page數量,須要注意的是,page table信息會放在物理內存中,每8個page就會佔據RAM中的1個byte。總的虛擬內存大小 = vm-page-size * vm-pages。

  ●vm-max-threads

  設置VM IO同時使用的線程數量。由於在進行內存交換時,對數據有編碼和解碼的過程,因此儘管IO設備在硬件上本上不能支持不少的併發讀寫,可是仍是若是你所保存的vlaue值比較大,將該值設大一些,仍是可以提高性能的。

  ●glueoutputbuf

  把小的輸出緩存放在一塊兒,以便可以在一個TCP packet中爲客戶端發送多個響應,具體原理和真實效果我不是很清楚。因此根據註釋,你不是很肯定的時候就設置成yes。

  ●hash-max-zipmap-entries

  在redis 2.0中引入了hash數據結構。當hash中包含超過指定元素個數而且最大的元素沒有超過臨界時,hash將以一種特殊的編碼方式(大大減小內存使用)來存儲,這裏能夠設置這兩個臨界值。

  ●activerehashing

  開啓以後,redis將在每100毫秒時使用1毫秒的CPU時間來對redis的hash表進行從新hash,能夠下降內存的使用。當你的使用場景中,有很是嚴格的實時性須要,不可以接受Redis時不時的對請求有2毫秒的延遲的話,把這項配置爲no。若是沒有這麼嚴格的實時性要求,能夠設置爲yes,以便可以儘量快的釋放內存。

13.redis客戶端(C語言)

上面介紹了redis 安裝和簡單使用操做,下面,咱們來介紹一下redis client端的編寫。

[root@localhost redis-2.2.12]# cd deps/hiredis/
[root@localhost hiredis]# make 

[root@localhost hiredis]# make install 

這種方式安裝的安裝庫,沒有到達默認目錄,須要咱們:
[root@localhost hiredis] cp libhiredis.so /usr/lib64 /usr/lib  (如果32系統只須要運行 cp libhiredis.so /usr/lib

[root@localhost hiredis]# gcc test.c -o test -lhiredis
[root@loaclhost hiredis]# ./test 

此時可能出現錯誤:

錯誤:expected identifier before numeric constant
錯誤:expected `}' before numeric constant

緣由是:問題出在一個枚舉enum類型上,發現與redis裏面的枚舉類型重複變量,改變一下枚舉類型的變量便可。

[root@localhost hiredis]# gcc example.c  -o example -lhiredis
[root@localhost hiredis]# ./example 

此時可能出現錯誤:

error while loading shared libraries: libhiredis.so.0.10: cannot open shared object file: No such file or directory

緣由是:是動態庫的問題,是系統找不到這個動態庫,此時記住sudo /sbin/ldconfig如下,更新一下系統動態庫配置。

可能出現錯誤:

error: hiredis/hiredis.h: No such file or directory

這是因爲缺乏hiredis依賴關係,解決方案:

On OSX run:

brew install hiredis

and on Ubuntu:

apt-get install libhiredis-dev

on other platforms:

git clone https://github.com/antirez/hiredis.git && cd hiredis && make && sudo make install && sudo ldconfig

編程時,能夠參照example.c 的實例便可。

測試代碼1:

  1. #include <stdio.h>  

  2.   

  3. #include <hiredis/hiredis.h>  

  4.   

  5. int main()  

  6. {  

  7.     redisContext* conn = redisConnect("127.0.0.1",6379);  

  8.     if(conn->err)   printf("connection error:%s\n",conn->errstr);  

  9.   

  10.     redisReply* reply = redisCommand(conn,"set foo 1234");  

  11.     freeReplyObject(reply);  

  12.   

  13.     reply = redisCommand(conn,"get foo");  

  14.   

  15.     printf("%s\n",reply->str);  

  16.     freeReplyObject(reply);  

  17.   

  18.     redisFree(conn);  

  19.   

  20.     return 0;  

  21.   

  22. }

在下面的代碼示例中,將給出兩種最爲經常使用的Redis命令操做方式,既普通調用方式和基於管線的調用方式。

  1.  #include <stdio.h>  

  2.  #include <stdlib.h>  

  3.  #include <stddef.h>  

  4.  #include <stdarg.h>  

  5.  #include <string.h>  

  6.  #include <assert.h>  

  7.  #include <hiredis/hiredis.h>  

  8.    

  9.  void doTest()  

  10.  {  

  11.      int timeout = 10000;  

  12.      struct timeval tv;  

  13.      tv.tv_sec = timeout / 1000;  

  14.      tv.tv_usec = timeout * 1000;  

  15.      //以帶有超時的方式連接Redis服務器,同時獲取與Redis鏈接的上下文對象。  

  16.      //該對象將用於其後全部與Redis操做的函數。  

  17.      redisContext* c = redisConnect((char*)"127.0.0.1", 6379);  

  18.      if (c->err) {  

  19.          redisFree(c);  

  20.          return;  

  21.      }  

  22.      const char* command1 = "set stest1 value9";  

  23.      redisReply* r = (redisReply*)redisCommand(c,command1);  

  24.      //須要注意的是,若是返回的對象是NULL,則表示客戶端和服務器之間出現嚴重錯誤,必須從新連接。  

  25.      //這裏只是舉例說明,簡便起見,後面的命令就再也不作這樣的判斷了。  

  26.      if (NULL == r) {  

  27.           redisFree(c);  

  28.          return;  

  29.      }  

  30.      //不一樣的Redis命令返回的數據類型不一樣,在獲取以前須要先判斷它的實際類型。  

  31.      //至於各類命令的返回值信息,能夠參考Redis的官方文檔,或者查看該系列博客的前幾篇  

  32.      //有關Redis各類數據類型的博客。:)  

  33.      //字符串類型的set命令的返回值的類型是REDIS_REPLY_STATUS,而後只有當返回信息是"OK"  

  34.      //時,才表示該命令執行成功。後面的例子以此類推,就再也不過多贅述了。  

  35.      if (!(r->type == REDIS_REPLY_STATUS && strcasecmp(r->str,"OK") == 0)) {  

  36.          printf("Failed to execute command[%s].\n",command1);  

  37.          freeReplyObject(r);  

  38.          redisFree(c);  

  39.          return;  

  40.      }  

  41.      //因爲後面重複使用該變量,因此須要提早釋放,不然內存泄漏。  

  42.      freeReplyObject(r);  

  43.      printf("Succeed to execute command[%s].\n",command1);  

  44.    

  45.      const char* command2 = "strlen stest1";  

  46.      r = (redisReply*)redisCommand(c,command2);  

  47.      if (r->type != REDIS_REPLY_INTEGER) {  

  48.          printf("Failed to execute command[%s].\n",command2);  

  49.          freeReplyObject(r);  

  50.          redisFree(c);  

  51.          return;  

  52.      }  

  53.      int length = r->integer;  

  54.      freeReplyObject(r);  

  55.      printf("The length of 'stest1' is %d.\n",length);  

  56.      printf("Succeed to execute command[%s].\n",command2);  

  57.    

  58.      const char* command3 = "get stest1";  

  59.      r = (redisReply*)redisCommand(c,command3);  

  60.      if (r->type != REDIS_REPLY_STRING) {  

  61.          printf("Failed to execute command[%s].\n",command3);  

  62.          freeReplyObject(r);  

  63.          redisFree(c);  

  64.          return;  

  65.      }  

  66.      printf("The value of 'stest1' is %s.\n",r->str);  

  67.      freeReplyObject(r);  

  68.      printf("Succeed to execute command[%s].\n",command3);  

  69.    

  70.      const char* command4 = "get stest2";  

  71.      r = (redisReply*)redisCommand(c,command4);  

  72.      //這裏須要先說明一下,因爲stest2鍵並不存在,所以Redis會返回空結果,這裏只是爲了演示。  

  73.      if (r->type != REDIS_REPLY_NIL) {  

  74.          printf("Failed to execute command[%s].\n",command4);  

  75.          freeReplyObject(r);  

  76.          redisFree(c);  

  77.          return;  

  78.      }  

  79.      freeReplyObject(r);  

  80.      printf("Succeed to execute command[%s].\n",command4);  

  81.    

  82.      const char* command5 = "mget stest1 stest2";  

  83.      r = (redisReply*)redisCommand(c,command5);  

  84.      //不論stest2存在與否,Redis都會給出結果,只是第二個值爲nil。  

  85.      //因爲有多個值返回,由於返回應答的類型是數組類型。  

  86.      if (r->type != REDIS_REPLY_ARRAY) {  

  87.          printf("Failed to execute command[%s].\n",command5);  

  88.          freeReplyObject(r);  

  89.          redisFree(c);  

  90.          //r->elements表示子元素的數量,無論請求的key是否存在,該值都等於請求是鍵的數量。  

  91.          assert(2 == r->elements);  

  92.          return;  

  93.      }  

  94.      int i;  

  95.       for (i = 0; i < r->elements; ++i) {  

  96.          redisReply* childReply = r->element[i];  

  97.          //以前已經介紹過,get命令返回的數據類型是string。  

  98.          //對於不存在key的返回值,其類型爲REDIS_REPLY_NIL。  

  99.          if (childReply->type == REDIS_REPLY_STRING)  

  100.              printf("The value is %s.\n",childReply->str);  

  101.      }  

  102.      //對於每個子應答,無需使用者單獨釋放,只需釋放最外部的redisReply便可。  

  103.      freeReplyObject(r);  

  104.      printf("Succeed to execute command[%s].\n",command5);  

  105.    

  106.      printf("Begin to test pipeline.\n");  

  107.      //該命令只是將待發送的命令寫入到上下文對象的輸出緩衝區中,直到調用後面的  

  108.      //redisGetReply命令纔會批量將緩衝區中的命令寫出到Redis服務器。這樣能夠  

  109.      //有效的減小客戶端與服務器之間的同步等候時間,以及網絡IO引發的延遲。  

  110.      //至於管線的具體性能優點,能夠考慮該系列博客中的管線主題。  

  111.     /* if (REDIS_OK != redisAppendCommand(c,command1) 

  112.          || REDIS_OK != redisAppendCommand(c,command2) 

  113.          || REDIS_OK != redisAppendCommand(c,command3) 

  114.          || REDIS_OK != redisAppendCommand(c,command4) 

  115.          || REDIS_OK != redisAppendCommand(c,command5)) { 

  116.          redisFree(c); 

  117.          return; 

  118.      } 

  119.  */  

  120.   

  121.     redisAppendCommand(c,command1);  

  122.     redisAppendCommand(c,command2);  

  123.     redisAppendCommand(c,command3);  

  124.     redisAppendCommand(c,command4);  

  125.     redisAppendCommand(c,command5);  

  126.      redisReply* reply = NULL;  

  127.      //對pipeline返回結果的處理方式,和前面代碼的處理方式徹底一直,這裏就再也不重複給出了。  

  128.      if (REDIS_OK != redisGetReply(c,(void**)&reply)) {  

  129.          printf("Failed to execute command[%s] with Pipeline.\n",command1);  

  130.          freeReplyObject(reply);  

  131.          redisFree(c);  

  132.      }  

  133.      freeReplyObject(reply);  

  134.      printf("Succeed to execute command[%s] with Pipeline.\n",command1);  

  135.    

  136.      if (REDIS_OK != redisGetReply(c,(void**)&reply)) {  

  137.          printf("Failed to execute command[%s] with Pipeline.\n",command2);  

  138.          freeReplyObject(reply);  

  139.          redisFree(c);  

  140.      }  

  141.      freeReplyObject(reply);  

  142.      printf("Succeed to execute command[%s] with Pipeline.\n",command2);  

  143.    

  144.      if (REDIS_OK != redisGetReply(c,(void**)&reply)) {  

  145.          printf("Failed to execute command[%s] with Pipeline.\n",command3);  

  146.          freeReplyObject(reply);  

  147.          redisFree(c);  

  148.      }  

  149.      freeReplyObject(reply);  

  150.      printf("Succeed to execute command[%s] with Pipeline.\n",command3);  

  151.    

  152.      if (REDIS_OK != redisGetReply(c,(void**)&reply)) {  

  153.          printf("Failed to execute command[%s] with Pipeline.\n",command4);  

  154.          freeReplyObject(reply);  

  155.          redisFree(c);  

  156.      }  

  157.      freeReplyObject(reply);  

  158.      printf("Succeed to execute command[%s] with Pipeline.\n",command4);  

  159.    

  160.      if (REDIS_OK != redisGetReply(c,(void**)&reply)) {  

  161.          printf("Failed to execute command[%s] with Pipeline.\n",command5);  

  162.          freeReplyObject(reply);  

  163.          redisFree(c);  

  164.      }  

  165.      freeReplyObject(reply);  

  166.      printf("Succeed to execute command[%s] with Pipeline.\n",command5);  

  167.      //因爲全部經過pipeline提交的命令結果均已爲返回,若是此時繼續調用redisGetReply,  

  168.      //將會致使該函數阻塞並掛起當前線程,直到有新的經過管線提交的命令結果返回。  

  169.      //最後不要忘記在退出前釋放當前鏈接的上下文對象。  

  170.      redisFree(c);  

  171.      return;  

  172.  }  

  173.    

  174.  int main()  

  175.  {  

  176.      doTest();  

  177.      return 0;  

  178.  }

14.redis的數據類型及操做命令

redis支持的數據類型包括StringHashListSetSorted Set,因爲redis本質上一個key-value db,因此首先從Key開始學習。

Key()

key也是字符串類型,可是key中不能包括邊界字符。

因爲key不是binary safe的字符串,因此像"my key""mykey\n"這樣包含空格和換行的key是不容許的。

順便說一下在redis內部並不限制使用binary字符,這是redis協議限制的。"\r\n"在協議格式中會做爲特殊字符。

關於key的一個格式約定介紹下,object-type:id:field。好比user:1000:passwordblog:xxidxx:title

key的長度最好不要太長。道理很明顯佔內存啊,並且查找時候相對短key也更慢。不過也推薦太短的key,好比u:1000:pwd,這樣的。顯然沒上面的user:1000:password可讀性好。

下面介紹下key相關的幾個命令,其餘的請看相關文檔:

命令

說明

示例

DEL key [key ...]

移除給定的一個或多個key。若是key不存在,則忽略該命令。

redis 127.0.0.1:6379> set name naxsu

OK

redis 127.0.0.1:6379> del name

(integer) 1

KEYS pattern

查找符合給定模式的key

KEYS *命中數據庫中全部key

redis 127.0.0.1:6379> mset one 1 two 2 three 3 four 4

OK

redis 127.0.0.1:6379> keys *

1) "four"

2) "three"

3) "two"

4) "one"

RANDOMKEY

從當前數據庫中隨機返回(不刪除)一個key

redis 127.0.0.1:6379> randomkey

"two"

TTL key

返回給定key的剩餘生存時間(time to live)(以秒爲單位),過時的key將被刪除

 

redis 127.0.0.1:6379> set name naxsu

OK

redis 127.0.0.1:6379> expire name 30

(integer) 1

redis 127.0.0.1:6379> ttl name

(integer) 25

EXISTS key

檢查給定key是否存在,若key存在,返回1,不然返回0

redis 127.0.0.1:6379> exists name

(integer) 0

redis 127.0.0.1:6379> exists one

(integer) 1

RENAME key newkey

key更名爲newkey

keynewkey相同或者key不存在時,返回一個錯誤。

newkey已經存在時,RENAME命令將覆蓋舊值。

redis 127.0.0.1:6379> rename one newone

TYPE key

返回key所儲存的值的類型

redis 127.0.0.1:6379> type two

string

String(字符串)

stringredis最基本的類型,並且string類型是二進制安全的。意思是redisstring能夠包含任何數據。好比jpg圖片或者序列化的對象。從內部實現來看其實string能夠看做byte數組,最大上限是1G字節。下面是string類型的定義。

struct sdshdr {

long len;

long free;

char buf[];

};

buf是個char數組用於存貯實際的字符串內容。其實charc#中的byte是等價的,都是一個字節

lenbuf數組的長度,free是數組中剩餘可用字節數。由此能夠理解爲何string類型是二進制安全的了。由於它本質上就是個byte數組,固然能夠包含任何數據了。另外string類型能夠被部分命令按int處理.好比incr等命令,下面詳細介紹。還有redis的其餘類型像listsetsorted sethash它們包含的元素與都只能是string類型。

 

下面介紹下String相關的一些命令,其餘的請看相關文檔:

命令

說明

示例

SET key value

將字符串值value關聯到key

若是key已經持有其餘值,SET就覆寫舊值,無視類型。

redis 127.0.0.1:6379> set name naxsu

OK

MSET key value [key value ...]

同時設置一個或多個key-value對。

redis 127.0.0.1:6379> mset one 1 two 2 three 3 four 4

OK

APPEND key value

若是key已經存在而且是一個字符串,APPEND命令將value追加到key原來的值以後

若是key不存在,APPEND就簡單地將給定key設爲value,就像執行SET key value同樣。

redis 127.0.0.1:6379> append name -neng

(integer) 10

redis 127.0.0.1:6379> get name

"naxsu-neng"

GET key

返回key所關聯的字符串值。

redis 127.0.0.1:6379> get name

"naxsu-neng"

STRLEN key

返回key所儲存的字符串值的長度

redis 127.0.0.1:6379> strlen name

(integer) 10

 

List(列表)

redislist類型其實就是一個每一個子元素都是string類型的雙向鏈表。因此[lr]push[lr]pop命令的算法時間複雜度都是O(1)

另外list會記錄鏈表的長度。因此llen操做也是O(1).鏈表的最大長度是(232次方-1)。咱們能夠經過push,pop操做從鏈表的頭部或者尾部添加刪除元素。這使得list既能夠用做棧,也能夠用做隊列。有意思的是listpop操做還有阻塞版本的。當咱們[lr]pop一個list對象時,若是list是空,或者不存在,會當即返回nil。可是阻塞版本的b[lr]pop能夠則能夠阻塞,固然能夠加超時時間,超時後也會返回nil。爲何要阻塞版本的pop呢,主要是爲了不輪詢。舉個簡單的例子若是咱們用list來實現一個工做隊列。執行任務的thread能夠調用阻塞版本的pop去獲取任務這樣就能夠避免輪詢去檢查是否有任務存在。當任務來時候工做線程能夠當即返回,也能夠避免輪詢帶來的延遲。

 

下面介紹下list相關的一些命令,其餘的請看相關文檔:

命令

說明

示例

LPUSH key value [value ...]

將一個或多個值value插入到列表key的表頭。

redis 127.0.0.1:6379> LPUSH mylist a b c

(integer) 3

RPUSH key value [value ...]

將一個或多個值value插入到列表key表尾

redis 127.0.0.1:6379> RPUSH mylist a b c

(integer) 6[6個元素中包括上例PUSH3]

LLEN key

返回列表key的長度

redis 127.0.0.1:6379> llen mylist

(integer) 6

LRANGE key start stop

返回列表key中指定區間內的元素,區間以偏移量startstop指定。

redis 127.0.0.1:6379> lrange mylist 0 6

1) "c"

2) "b"

3) "a"

4) "a"

5) "b"

6) "c"

LPOP key

移除並返回列表key的頭元素

redis 127.0.0.1:6379> lpop mylist

"c"

RPOP key

移除並返回列表key的尾元素

redis 127.0.0.1:6379> rpop mylist

"c"

 

Set(集合)

 redissetstring類型的無序集合。set元素最大能夠包含(232次方-1)個元素。set的是經過hash table實現的,因此添加,刪除,查找的複雜度都是O(1)hash table會隨着添加或者刪除自動的調整大小。須要注意的是調整hash table大小時候須要同步(獲取寫鎖)會阻塞其餘讀寫操做。可能不久後就會改用跳錶(skip list)來實現跳錶已經在sorted set中使用了。關於set集合類型除了基本的添加刪除操做,其餘有用的操做還包含集合的取並集(union),交集(intersection),差集(difference)。經過這些操做能夠很容易的實現sns中的好友推薦和blogtag功能。

 

下面介紹下set相關的一些命令,其餘的請看相關文檔:

命令

說明

示例

SADD key member [member ...]

將一個或多個member元素加入到集合key當中,已經存在於集合的member元素將被忽略

redis 127.0.0.1:6379> sadd languages java c lisp python ruby

(integer) 5

SMEMBERS key

返回集合key中的全部成員

redis 127.0.0.1:6379> smembers languages

1) "c"

2) "lisp"

3) "python"

4) "java"

5) "ruby"

SREM key member [member ...]

移除集合key中的一個或多個member元素

redis 127.0.0.1:6379> srem languages lisp

(integer) 1

SISMEMBER key member

判斷member元素是不是集合key的成員

redis 127.0.0.1:6379> SISMEMBER languages php

(integer) 0

SCARD key

返回集合key基數(集合中元素的數量)

redis 127.0.0.1:6379> SCARD languages

(integer) 4

SINTER key [key ...]

返回一個集合的所有成員,該集合是全部給定集合的交集

redis 127.0.0.1:6379> sadd group_1 lilei tom jack

(integer) 3

redis 127.0.0.1:6379> sadd group_2 naxsu jack

(integer) 2

redis 127.0.0.1:6379> sinter group_1 group_2

1) "jack"

SUNION key [key ...]

返回一個集合的所有成員,該集合是全部給定集合的並集

redis 127.0.0.1:6379> sunion group_1 group_2

1) "naxsu"

2) "lilei"

3) "tom"

4) "jack"

SDIFF key [key ...]

返回一個集合的所有成員,該集合是全部給定集合的差集

redis 127.0.0.1:6379> SDIFF group_1 group_2

1) "lilei"

2) "tom"

 

Sorted Set (有序集)

set同樣sorted set也是string類型元素的集合,不一樣的是每一個元素都會關聯一個double類型的score

sorted set的實現是skip listhash table的混合體,當元素被添加到集合中時,一個元素到score的映射被添加到hash table中,因此給定一個元素獲取score的開銷是O(1),另外一個score到元素的映射被添加到skip list,並按照score排序,因此就能夠有序的獲取集合中的元素。添加,刪除操做開銷都是O(log(N))skip list的開銷一致,redisskip list實現用的是雙向鏈表,這樣就能夠逆序從尾部取元素。sorted set最常常的使用方式應該是做爲索引來使用.咱們能夠把要排序的字段做爲score存儲,對象的id當元素存儲。

 

下面介紹下sorted set相關的一些命令,其餘的請看相關文檔:

命令

說明

示例

ZADD key score member [[score member] [score member] ...]

將一個或多個member元素及其score值加入到有序集key當中

redis 127.0.0.1:6379> ZADD page_rank 9 baidu.com 8 bing.com 10 google.com

(integer) 3

ZRANGE key start stop [WITHSCORES]

返回有序集key中,指定區間內的成員其中成員的位置按score值遞增(從小到大)來排序

 

ZREVRANGE key start stop [WITHSCORES] 其中成員的位置按score值遞減(從大到小)來排列

redis 127.0.0.1:6379> ZRANGE page_rank 0 -1 WITHSCORES

1) "bing.com"

2) "8"

3) "baidu.com"

4) "9"

5) "google.com"

6) "10"

ZREM key member [member ...]

移除有序集key中的一個或多個成員,不存在的成員將被忽略

redis 127.0.0.1:6379> ZREM page_rank google.com

(integer) 1

ZCARD key

返回有序集key的基數

redis 127.0.0.1:6379> zcard page_rank

(integer) 2

ZCOUNT key min max

返回有序集key中,score值在minmax之間(默認包括score值等於minmax)的成員

redis 127.0.0.1:6379> zcount page_rank 7 9

(integer) 2

ZSCORE key member

返回有序集key中,成員memberscore

redis 127.0.0.1:6379> zscore page_rank baidu.com

"9"

 

Hash (哈希表)

redis hash是一個string類型的fieldvalue的映射表.它的添加,刪除操做都是O(1)(平均).hash特別適合用於存儲對象。相較於將對象的每一個字段存成單個string類型。將一個對象存儲在hash類型中會佔用更少的內存,而且能夠更方便的存取整個對象。省內存的緣由是新建一個hash對象時開始是用zipmap(又稱爲small hash)來存儲的。這個zipmap其實並非hash table,可是zipmap相比正常的hash實現能夠節省很多hash自己須要的一些元數據存儲開銷。儘管zipmap的添加,刪除,查找都是O(n),可是因爲通常對象的field數量都不太多。因此使用zipmap也是很快的,也就是說添加刪除平均仍是O(1)。若是field或者value的大小超出必定限制後,redis會在內部自動將zipmap替換成正常的hash實現這個限制能夠在配置文件中指定

hash-max-zipmap-entries 64 #配置字段最多64

hash-max-zipmap-value 512 #配置value最大爲512字節

 

下面介紹下hash相關的一些命令,其餘的請看相關文檔:

命令

說明

示例

HSET key field value

將哈希表key中的域field的值設爲value

redis 127.0.0.1:6379> hset website google www.google.com

HGET key field

返回哈希表key中給定域field的值

redis 127.0.0.1:6379> hget website google

"www.google.com"

HDEL key field [field ...]

刪除哈希表key中的一個或多個指定域,不存在的域將被忽略

redis 127.0.0.1:6379> hdel website google

(integer) 1

HMSET key field value [field value ...]

同時將多個field - value(-)對設置到哈希表key

redis 127.0.0.1:6379> HMSET website google www.google.com yahoo www.yahoo.com

OK

HMGET key field [field ...]

返回哈希表key中,一個或多個給定域的值

redis 127.0.0.1:6379> hmget website google yahoo

1) "www.google.com"

2) "www.yahoo.com"

HGETALL key

返回哈希表key中,全部的域和值

redis 127.0.0.1:6379> hgetall website

1) "naxsu"

2) "www.naxsu.com"

3) "google"

4) "www.google.com"

5) "yahoo"

6) "www.yahoo.com"

HLEN key

返回哈希表key中域的數量

redis 127.0.0.1:6379> hlen website

(integer) 3

HEXISTS key field

查看哈希表key中,給定域field是否存在

redis 127.0.0.1:6379> HEXISTS website baidu

(integer) 0

HKEYS key

返回哈希表key中的全部域

redis 127.0.0.1:6379> hkeys website

1) "naxsu"

2) "google"

3) "yahoo"

HVALS key

返回哈希表key中的全部值

redis 127.0.0.1:6379> hvals website

1) "www.naxsu.com"

2) "www.google.com"

3) "www.yahoo.com"

 

到此,redis的數據類型已經所有講完了

相關文章
相關標籤/搜索