1. 程式人生 > >Redis資料結構介紹

Redis資料結構介紹

相比於memcache 作為快取服務,redis 提供了更為豐富的資料結構:String, List,Set,SortedSet,Hash等。對於這五種資料結構,可以結合Java中的對應的類來進行理解,其中String資料結構對應Object類 (任意物件都會序列化成string來儲存),List資料結構對應java.util.List介面的實現類java.util.LinkedList,Set資料結構對應java.util.Set介面,SortedSet資料結構對應java.util.SortedSet介面,Hash資料結構對應java.util.HashMap類。下面簡單介紹下幾種資料結構以及使用場景。

String

String型別是Redis中最為基礎的資料儲存型別,是二進位制安全的字串,該型別可以接受任何格式的資料,如JPEG影象資料或Json物件描述資訊等。在Redis中String型別的Value最多可以容納的資料長度是512M,在squirrel-client中Value限制的大小是1M。相對於其他的幾種資料結構,只有String型別的命令在寫入key的時候可以帶有預設的過期時間(在squirrel-client中,對於String型別的命令只有set,add和multiset命令會自動設定過期時間,且過期時間為使用category的過期時間),對於其他的資料結構,key預設是不過期的,如果需要設定過期時間,必須顯示呼叫expire函式設定過期時間。在squirrel-client中,所有的物件都會被序列化成String存到叢集中,因此所有的資料都可以作為String型別來儲存

使用場景:value較小、模型簡單的 value可以使用String型別儲存,對於一些特殊的資料結構,比如List、Set等,建議採用相應的下面介紹的List和Set資料結構進行儲存,這樣不僅可以節省儲存空間還可以提高操作效率。

List

List型別是按照插入順序排序的字串連結串列。和資料結構中的普通連結串列一樣,可以在其頭部(left)和尾部(right)新增新的元素。在插入時,如果該鍵並不存在,Redis將為該鍵建立一個新的連結串列。與此相反,如果連結串列中所有的元素均被移除,那麼該鍵也將會被從資料庫中刪除。

從元素插入和刪除的效率視角來看,如果是在連結串列的兩頭插入或刪除元素,這將會是非常高效的操作,即使連結串列中已經儲存了百萬條記錄,該操作也可以在常量時間內完成。然而需要說明的是,如果元素插入或刪除操作是作用於連結串列中間,那將會是非常低效的。

使用場景:在評級系統中,比如社會化新聞網站,你可以把每個新提交的連結新增到一個list,用LRANGE可簡單的對結果分頁;在部落格引擎實現中,你可為每篇日誌設定一個list,在該list中推入進部落格評論等等。

Set

Set型別是沒有排序的字串集合,和List型別一樣,也可以在該型別的資料值上執行新增、刪除或判斷某一元素是否存在等操作。和List型別不同的是,Set集合中不允許出現重複的元素,如果多次新增相同元素,Set中將僅保留該元素的一份拷貝。

使用場景:可以使用Redis的Set資料型別跟蹤一些唯一性資料,比如訪問某一部落格的唯一IP地址資訊。對於此場景,僅需在每次訪問該部落格時將訪問者的IP存入Redis中,Set資料型別會自動保證IP地址的唯一性。

SortedSet

SortedSet和Set型別極為相似,它們都是字串的集合,都不允許重複的成員出現在一個Set中。它們之間的主要差別是SortedSet中的每一個成員都會有一個分數(score)與之關聯,Redis正是通過分數來為集合中的成員進行從小到大的排序。需要額外指出的是,儘管SortedSet中的成員必須是唯一的,但是分數(score)卻是可以重複的。在SortedSet中新增、刪除或更新一個成員都是非常快速的操作,其時間複雜度為O(logn)。由於SortedSet中的成員在集合中的位置是有序的,因此,即便是訪問位於集合中部的成員也仍然是非常高效的。

使用場景:

  1. 可以用於一個大型線上遊戲的積分排行榜。每當玩家的分數發生變化時,可以執行ZADD命令更新玩家的分數,此後再通過ZRANGE命令獲取積分TOP TEN的使用者資訊。當然也可以利用ZRANK命令通過username來獲取玩家的排行資訊。最後將組合使用ZRANGE和ZRANK命令快速的獲取和某個玩家積分相近的其他使用者的資訊。

  2. SortedSet型別還可用於構建索引資料。

  3. 建立一個SortedSet中元素個數不要超過 1 W。

Hash

Hash型別相當於Java中的HashMap。所以該型別非常適合於儲存值物件的資訊,比如User物件含有Username、Password和Age等屬性,可以使用hash來儲存User,每個field對應一個屬性,好處是可以做到部分更新、獲取。如果Hash中包含很少的欄位,那麼該型別的資料也將僅佔用很少的磁碟空間。

使用場景:

       1,對於海量資料的情況,可以自己對資料進行分桶,然後使用Hash結構來儲存。對於很多value為簡單的字串,做過測試,採用hash儲存更節省空間。

       2,將物件儲存為Hash結構而不是String,可以每次只更新、獲取Hash中的一個field,這樣可以提高效率。

HyperLogLog

HyperLogLog型別用來進行基數統計。利用HyperLogLog,使用者可以使用少量固定大小的記憶體,來統計集合中唯一元素的數量(每個HyperLogLog佔用12KB記憶體,可以計算接近264個不同元素的基數)。關於HyperLogLog的原理,可以參見:神奇的HyperLogLog演算法

利用HyperLogLog得到的基數統計結果,不是精確值,而是一個帶有0.81%標準差(standard error)的近似值。所以,HyperLogLog適用於一些對於統計結果精確度要求不是特別高的場景。

使用場景:

1.可以用於統計一個網站的UV。利用HyperLogLog來統計訪問一個網站