Redis不是簡單的鍵值存儲,它其實是一個數據結構服務器,支持各類類型的值。這意味着,儘管在傳統的鍵值存儲中,你將字符串鍵關聯到字符串值,可是在Redis中,該值不只限於簡單的字符串,還能夠保存更復雜的數據結構。如下是Redis支持的全部數據結構的列表,本教程將分別進行介紹:redis
從命令參考中掌握這些數據類型的工做方式以及如何使用它們來解決給定問題並不老是那麼容易,所以,本文檔是Redis數據類型及其最多見模式的速成教程。對於全部示例,咱們將使用redis-cli
實用程序(一種簡單但方便的命令行實用程序)針對Redis服務器發出命令。數據庫
Redis鍵是二進制安全的,這意味着你可使用任何二進制序列做爲鍵,從「foo」之類的字符串到JPEG文件的內容,空字符串也是有效的鍵。數組
有關鍵的其餘一些規則:緩存
Redis字符串類型是你能夠與Redis鍵關聯的最簡單的值類型,它是Memcached中惟一的數據類型,所以對於新手來講,在Redis中使用它也是很天然的。安全
因爲Redis鍵是字符串,所以當咱們也使用字符串類型做爲值時,咱們會將一個字符串映射到另外一個字符串,字符串數據類型對於許多用例頗有用,例如緩存HTML片斷或頁面。服務器
讓咱們使用redis-cli
來研究字符串類型(在本教程中,全部示例都將經過redis-cli
執行)。數據結構
> set mykey somevalue OK > get mykey "somevalue"
如你所見,使用SET
和GET
命令是咱們設置和檢索字符串值的方式,請注意,即便鍵已與非字符串值相關聯,SET
也會替換已存儲在鍵中的任何現有值(即便鍵已存在),所以SET
執行分配。網站
值能夠是各類類型的字符串(包括二進制數據),例如,你能夠在值內存儲jpeg圖像,值不能大於512MB。命令行
SET
命令具備有趣的選項,這些選項做爲附加參數提供,例如,若是鍵已經存在,我可能會要求SET
失敗,或者相反,只有鍵已經存在時,它纔會成功:日誌
> set mykey newval nx (nil) > set mykey newval xx OK
即便字符串是Redis的基本值,你也可使用它們執行一些有趣的操做,例如,一個是原子增量:
> set counter 100 OK > incr counter (integer) 101 > incr counter (integer) 102 > incrby counter 50 (integer) 152
INCR
命令將字符串值解析爲整數,將其遞增1,最後將得到的值設置爲新值,還有其餘相似的命令,例如INCRBY
、DECR
和DECRBY
,在內部,它始終是相同的命令,其執行方式略有不一樣。
INCR
是原子的意味着什麼?即便使用相同鍵發出INCR
的多個客戶端也永遠不會進入競爭狀態。例如,永遠不會發生客戶端1讀取「10」,客戶端2同時讀取「10」的狀況,二者都遞增到11,並將新值設置爲11。最終值將始終爲12,而且在全部其餘客戶端未同時執行命令時執行讀取遞增設置操做。
有許多用於操做字符串的命令,例如,GETSET
命令將鍵設置爲新值,並返回舊值做爲結果。你可使用此命令,例如,若是你有一個系統,每次你的網站收到新訪問者時都使用INCR
來遞增Redis鍵,你可能但願每小時收集一次此信息,而不丟失一個增量,你能夠GETSET
鍵,爲其分配新值「0」,而後回讀舊值。
在單個命令中設置或檢索多個鍵的值的功能對於減小延遲也頗有用,所以,有MSET
和MGET
命令:
> mset a 10 b 20 c 30 OK > mget a b c 1) "10" 2) "20" 3) "30"
使用MGET
時,Redis返回一個值數組。
有些命令沒有在特定類型上定義,可是在與鍵的空間進行交互時頗有用,所以能夠與任何類型的鍵一塊兒使用。
例如,EXISTS
命令返回1或0表示數據庫中是否存在給定的鍵,而DEL
命令則刪除鍵和關聯的值(不管該值是什麼)。
> set mykey hello OK > exists mykey (integer) 1 > del mykey (integer) 1 > exists mykey (integer) 0
從示例中,你還能夠看到DEL
自己如何返回1或0,具體取決於鍵已刪除(存在)或未刪除(不存在具備該名稱的此類鍵)。
有許多與鍵空間相關的命令,可是以上兩個是必不可少的,與TYPE
命令一塊兒使用,TYPE
命令返回存儲在指定鍵處的值的類型:
> set mykey x OK > type mykey string > del mykey (integer) 1 > type mykey none
在繼續使用更復雜的數據結構以前,咱們須要討論另外一個功能,該功能不管值類型如何均可以工做,而且稱爲Redis expires,基本上,你能夠爲鍵設置超時時間,這是有限的生存時間。生存時間過去後,該鍵將自動銷燬,就像用戶使用該鍵調用DEL
命令同樣。
有關Redis expires的一些快速信息:
設置過時時間很簡單:
> set key some-value OK > expire key 5 (integer) 1 > get key (immediately) "some-value" > get key (after some time) (nil)
因爲第二次調用延遲了5秒鐘以上,所以兩次調用之間的鍵消失了,在上面的示例中,咱們使用EXPIRE
來設置過時時間(也可使用它來爲已具備過時時間的鍵設置不一樣的過時時間,例如可使用PERSIST
來刪除過時時間並使鍵永久保留)。可是,咱們還可使用其餘Redis命令來建立帶有過時時間的鍵,例如,使用SET
選項:
> set key 100 ex 10 OK > ttl key (integer) 9
上面的示例設置了一個字符串值100的鍵,該鍵的過時時間爲10秒,以後,調用TTL
命令以檢查鍵的剩餘生存時間。
爲了設置並檢查以毫秒爲單位的過時時間,請查看PEXPIRE
和PTTL
命令以及SET
選項的完整列表。
爲了解釋List數據類型,最好從一些理論上入手,由於信息技術人員常常以不適當的方式使用List一詞。例如,「Python列表」不是名稱(鏈表)所建議的,而是數組(在Ruby中,相同的數據類型實際上稱爲數組)。
從很是廣泛的角度來看,列表只是一個有序元素的序列:10,20,1,2,3是一個列表。可是,使用數組實現的列表的屬性與使用鏈表實現的列表的屬性很是不一樣,Redis列表經過鏈表實現。這意味着即便列表中有數百萬個元素,在列表的開頭或結尾添加新元素的操做也會在恆定時間內執行。使用LPUSH
命令將新元素添加到具備10個元素的列表的開頭的速度與將元素添加到具備1000萬個元素的列表的開頭的速度相同。
不利之處是什麼?在使用數組實現的列表中,按索引訪問元素的速度很是快(恆定時間索引訪問),而在經過鏈表實現的列表中訪問速度不是那麼快(其中該操做須要與所訪問元素的索引成比例的工做量)。
Redis列表是使用鏈表實現的,由於對於數據庫系統而言,相當重要的是可以以很是快的方式將元素添加到很長的列表中,稍後你將看到,另外一個強大的優點是Redis列表能夠在恆定的時間內以恆定的長度獲取。
當快速訪問大量元素的中間很重要時,可使用另外一種數據結構,稱爲排序集,排序集將在本教程的後面部分介紹。
LPUSH
命令將新元素添加到列表的左側(頂部),而RPUSH
命令將新元素添加到列表的右側(尾部),最後,LRANGE
命令從列表中提取元素範圍:
> rpush mylist A (integer) 1 > rpush mylist B (integer) 2 > lpush mylist first (integer) 3 > lrange mylist 0 -1 1) "first" 2) "A" 3) "B"
請注意,LRANGE
須要兩個索引,要返回的範圍的第一個和最後一個元素,兩個索引均可覺得負,告訴Redis從末尾開始計數:所以-1是列表的最後一個元素,-2是列表的倒數第二個元素,依此類推。
如你所見,RPUSH
在列表的右側附加了元素,而最後的LPUSH
在左側附加了元素。
這兩個命令都是可變參數命令,這意味着你能夠在單個調用中隨意將多個元素推入列表中:
> rpush mylist 1 2 3 4 5 "foo bar" (integer) 9 > lrange mylist 0 -1 1) "first" 2) "A" 3) "B" 4) "1" 5) "2" 6) "3" 7) "4" 8) "5" 9) "foo bar"
Redis列表上定義的一項重要操做是彈出元素的能力,彈出元素是同時從列表中檢索元素並將其從列表中刪除的操做,你能夠從左側和右側彈出元素,相似於在列表的兩側推送元素的方式:
> rpush mylist a b c (integer) 3 > rpop mylist "c" > rpop mylist "b" > rpop mylist "a"
咱們添加了三個元素,並彈出了三個元素,所以在此命令序列的最後,列表爲空,沒有其餘要彈出的元素,若是咱們嘗試彈出另外一個元素,這是咱們獲得的結果:
> rpop mylist (nil)
Redis返回NULL
值以表示列表中沒有元素。