Redis 參考文檔(Redis數據類型介紹)

Redis數據類型介紹

Redis不是簡單的鍵值存儲,它其實是一個數據結構服務器,支持各類類型的值。這意味着,儘管在傳統的鍵值存儲中,你將字符串鍵關聯到字符串值,可是在Redis中,該值不只限於簡單的字符串,還能夠保存更復雜的數據結構。如下是Redis支持的全部數據結構的列表,本教程將分別進行介紹:redis

  • 二進制安全字符串。
  • 列表:根據插入順序排序的字符串元素集合,它們基本上是鏈表。
  • 集:惟1、未排序的字符串元素的集合。
  • 排序的集,相似於集,但每一個字符串元素都與一個浮點數字值(稱爲分數)相關聯。元素老是按它們的分數排序,所以與集不一樣,能夠檢索元素的範圍(例如,你可能會問:給我前10個或後10個)。
  • 哈希,是由與值相關聯的字段組成的映射,字段和值都是字符串,這與Ruby或Python哈希很是類似。
  • 位數組(或簡稱爲位圖):可使用特殊命令像位數組同樣處理字符串值:你能夠設置和清除單個位、計數全部設置爲1的位、找到第一個設置或未設置的位,等等。
  • HyperLogLogs:這是一種機率數據結構,用於估計集的基數,別懼怕,它比看起來更簡單...請參閱本教程後面的HyperLogLog部分。
  • 流:僅附加的相似映射的條目的集合,提供抽象的日誌數據類型。

從命令參考中掌握這些數據類型的工做方式以及如何使用它們來解決給定問題並不老是那麼容易,所以,本文檔是Redis數據類型及其最多見模式的速成教程。對於全部示例,咱們將使用redis-cli實用程序(一種簡單但方便的命令行實用程序)針對Redis服務器發出命令。數據庫

Redis鍵

Redis鍵是二進制安全的,這意味着你可使用任何二進制序列做爲鍵,從「foo」之類的字符串到JPEG文件的內容,空字符串也是有效的鍵。數組

有關鍵的其餘一些規則:緩存

  • 太長的鍵不是一個好主意,例如,1024字節的鍵不只在內存方面是一個壞主意,並且還由於在數據集中查找鍵可能須要進行幾回代價高昂的鍵比較。即便手頭的任務是匹配一個大值的存在,對它進行哈希(例如使用SHA1)也是一個更好的主意,尤爲是從內存和帶寬的角度來看。
  • 很是短的鍵一般不是一個好主意,若是你能夠改寫「user:1000:followers」,那麼將「u1000flw」做爲鍵寫的就沒有意義了。與鍵對象自己和值對象使用的空間相比,後者更具可讀性,而且添加的空間較小,雖然短鍵顯然會消耗較少的內存,可是你的工做是找到合適的平衡。
  • 試着堅持一個模式,例如,「object-type:id」是一個好主意,例如「user:1000」,點或破折號一般用於多字字段,例如「comment:10000:reply.to」或「comment:10000:reply-to」中。
  • 容許的最大鍵大小爲512MB。

Redis字符串

Redis字符串類型是你能夠與Redis鍵關聯的最簡單的值類型,它是Memcached中惟一的數據類型,所以對於新手來講,在Redis中使用它也是很天然的。安全

因爲Redis鍵是字符串,所以當咱們也使用字符串類型做爲值時,咱們會將一個字符串映射到另外一個字符串,字符串數據類型對於許多用例頗有用,例如緩存HTML片斷或頁面。服務器

讓咱們使用redis-cli來研究字符串類型(在本教程中,全部示例都將經過redis-cli執行)。數據結構

> set mykey somevalue
OK
> get mykey
"somevalue"

如你所見,使用SETGET命令是咱們設置和檢索字符串值的方式,請注意,即便鍵已與非字符串值相關聯,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,最後將得到的值設置爲新值,還有其餘相似的命令,例如INCRBYDECRDECRBY,在內部,它始終是相同的命令,其執行方式略有不一樣。

INCR是原子的意味着什麼?即便使用相同鍵發出INCR的多個客戶端也永遠不會進入競爭狀態。例如,永遠不會發生客戶端1讀取「10」,客戶端2同時讀取「10」的狀況,二者都遞增到11,並將新值設置爲11。最終值將始終爲12,而且在全部其餘客戶端未同時執行命令時執行讀取遞增設置操做。

有許多用於操做字符串的命令,例如,GETSET命令將鍵設置爲新值,並返回舊值做爲結果。你可使用此命令,例如,若是你有一個系統,每次你的網站收到新訪問者時都使用INCR來遞增Redis鍵,你可能但願每小時收集一次此信息,而不丟失一個增量,你能夠GETSET鍵,爲其分配新值「0」,而後回讀舊值。

在單個命令中設置或檢索多個鍵的值的功能對於減小延遲也頗有用,所以,有MSETMGET命令:

> 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:時間有限的鍵

在繼續使用更復雜的數據結構以前,咱們須要討論另外一個功能,該功能不管值類型如何均可以工做,而且稱爲Redis expires,基本上,你能夠爲鍵設置超時時間,這是有限的生存時間。生存時間過去後,該鍵將自動銷燬,就像用戶使用該鍵調用DEL命令同樣。

有關Redis expires的一些快速信息:

  • 可使用秒或毫秒精度進行設置。
  • 可是,到期時間分辨率始終爲1毫秒。
  • 有關過時的信息被複制並保留在磁盤上,當你的Redis服務器保持中止狀態時,時間實際上已通過去了(這意味着Redis保存了鍵過時的日期)。

設置過時時間很簡單:

> 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命令以檢查鍵的剩餘生存時間。

爲了設置並檢查以毫秒爲單位的過時時間,請查看PEXPIREPTTL命令以及SET選項的完整列表。

Redis列表

爲了解釋List數據類型,最好從一些理論上入手,由於信息技術人員常常以不適當的方式使用List一詞。例如,「Python列表」不是名稱(鏈表)所建議的,而是數組(在Ruby中,相同的數據類型實際上稱爲數組)。

從很是廣泛的角度來看,列表只是一個有序元素的序列:10,20,1,2,3是一個列表。可是,使用數組實現的列表的屬性與使用鏈表實現的列表的屬性很是不一樣,Redis列表經過鏈表實現。這意味着即便列表中有數百萬個元素,在列表的開頭或結尾添加新元素的操做也會在恆定時間內執行。使用LPUSH命令將新元素添加到具備10個元素的列表的開頭的速度與將元素添加到具備1000萬個元素的列表的開頭的速度相同。

不利之處是什麼?在使用數組實現的列表中,按索引訪問元素的速度很是快(恆定時間索引訪問),而在經過鏈表實現的列表中訪問速度不是那麼快(其中該操做須要與所訪問元素的索引成比例的工做量)。

Redis列表是使用鏈表實現的,由於對於數據庫系統而言,相當重要的是可以以很是快的方式將元素添加到很長的列表中,稍後你將看到,另外一個強大的優點是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值以表示列表中沒有元素。

相關文章
相關標籤/搜索