1. 程式人生 > >Redis資料結構:點陣圖

Redis資料結構:點陣圖

原文:https://scalegrid.io/blog/introduction-to-redis-data-structure-bitmaps/

點陣圖(也稱為位陣列,位向量等)是緊湊儲存位的陣列資料結構。它可以用來實現一個簡單的集資料結構。位陣列可以有效地利用硬體中的位級並行性來快速執行操作。

 

Redis是一種記憶體資料結構伺服器,它為位操作操作提供支援。但是,Redis中的點陣圖沒有特殊的資料結構。相反,基本的Redis結構支援位級操作:字串。現在,Redis字串的最大長度為512 MB。因此,Redis可以對映為點陣圖的最大域是2^32(512 MB = 2^29位元組= 2^32位)。

Redis中的位相關操作有兩種:恆定時間(O(1)),例如,獲取/設定特定位的操作和基本上對一組位操作的O(N)操作。在這些情況下,N是操作需要處理的位長度。我們來看一些例子。

命令

 

#SETBIT鍵偏移值:將位值'value'儲存在'key'的偏移'offset'處。O(1)
#返回儲存在該偏移處的原始位值。
127.0.0.1:6379> setbit k 10 1
(整數)0
#GETBIT鍵偏移:在'key'中獲取'offset'的值。O(1)
127.0.0.1:6379> getbit k 10
(整數)1
127.0.0.1:6379> getbit k 11
(整數)0
127.0.0.1:6379> getbit k 0
(整數)0
127.0.0.1:6379> setbit k 9 1
(整數)0
127.0.0.1:6379> setbit k 8 1
(整數)0
#並且因為它仍然是一個通用字串,這裡是一個get。
127.0.0.1:6379>得到k
“\ X00 \ xe0”
#“\ x00 \ xe0” - >“0000 0000 111”
#BITCOUNT key [start end]:範圍內的設定位數。上)
#重要提示:start和end是位元組而不是位
127.0.0.1:6379> bitcount k
(整數)3
127.0.0.1:6379>設定m“喵”
好
#meow  - > 01101101 01100101 01101111 01110111 
127.0.0.1:6379> bitcount m
(整數)21
#BITPOS鍵位[start] [end]:鍵範圍內1或0的第1個位置。上)
127.0.0.1:6379>設定mykey“\ xff \ xf0 \ x00”
好
127.0.0.1:6379> BITPOS mykey 0
(整數)12

除了操作key本身的運算子之外,BITOP運算子還用於在多個key之間進行逐位邏輯運算。

 

#BITOP操作destkey鍵[key ...]。上)
#操作可以是AND,OR,XOR和NOT
127.0.0.1:6379>設定“\ xff \ xff”
好
127.0.0.1:6379> bitop not nota a
(整數)2
127.0.0.1:6379>得到nota
“\ X00 \ X00”
127.0.0.1:6379>設定b“\ x0f \ x0f”
好
127.0.0.1:6379>設定c“\ xf0 \ xf0”
好
127.0.0.1:6379> BITOP OR orbc bc
(整數)2
127.0.0.1:6379>獲取orbc
“\ XFF \ XFF”
127.0.0.1:6379> BITOP和andbc bc
(整數)2
127.0.0.1:6379> get andbc
“\ X00 \ X00”
127.0.0.1:6379> BITOP XOR xorbc bc
(整數)2
127.0.0.1:6379>獲取xorbc
“\ XFF \ XFF”
 

內幕

由於點陣圖操作沒有自己的資料結構,因此沒有特定的資料結構可供描述。Redis字串本身實現為二進位制安全字串。Redis字串資料結構在內部稱為簡單動態字串(SDS)。它本質上是一個原生的char [],帶有一些額外的簿記資訊。具體的實現細節可以在這裡找到。

點陣圖函式的實現位於檔案bitops.c中

PS:鑑於位操作演算法對關鍵作業系統和圖形功能的重要性,大多數架構都為此類操作提供了特殊指令。閱讀各種有趣的計算機算術演算法的好地方是經典的Hacker's Delight

 

應用

這個流行的GetSpool部落格是使用點陣圖在大型資料集上進行實時分析的一個很好的例子。它也是點陣圖的經典用例的一個例子:將極大域的布林資訊儲存到(相對)小空間中,同時保持良好的效能。

大小通常是真正大型點陣圖的關注點,因為大多數有用的操作都是O(N)。為了避免使用大的key,Redis文件建議將大的key分成多個較小的key。在關鍵變大之前,BITCOUNT表現仍然可以接受。此時,建議分割鍵或使用範圍引數逐步查詢。處理慢BITOP操作的建議是在slave上執行它。因此,一般來說,處理中等大小的key,並通過將key分成多個key來規劃未來的潛在增長是有意義的。

 bitmap VS Sets

Sets提供的功能性質和bitmap操作類似。因此,這兩種方法中哪一種更好會讓人感到困惑。取決於實際情況。顯然,此討論僅對sets和bitmap可以實現的操作型別有效。

Sets通常效率很高,並且可以很好地擴充套件,通常是首選的資料結構,除非資料大到無法支援。Sets也更易於管理,程式和除錯適用於大多數應用程式。不應低估Sets的易用性:操作bitmap的程式碼通常難以閱讀,理解,除錯和維護。即使值得範圍非常大,Sets仍可能是合適的。例如,如果應用程式旨在跟蹤對流行的電子商務站點的每日訪問,則結果可能仍然適合於Sets,因為通常僅5-10%的整個使用者群將每天訪問該站點。對於預計每天登入60%的使用者群的網站來說,這顯然會發生變化。然後,鑑於在大量key上的邏輯位操作的大小和效能,點陣圖變得更相關。Redis sets還具有不必將ID對映到位偏移的獨特優勢。同樣,如果您的值大於2^32,那麼Redis的sets 比點陣圖劃分域更容易使用。

針對MOOC的分析

下邊是可以應用Redis點陣圖操作的示例。比如說,您正在執行一個非常受歡迎的線上MOOC,數十萬學生已經註冊了該MOOC。促進課程的學術團隊需要一個儀表板,他們可以看到學生進度的實時狀態以及註冊學生的一般背景。您決定通過Redis點陣圖操作實現此功能。這是一步一步的方法。

  1. 建立計劃以在學生ID和點陣圖偏移之間進行對映。它可能就像ID是點陣圖中的偏移一樣簡單。
  2. 課程開始後,建立並填充各種與人口統計相關的點陣圖。例如,從同一所大學,教育水平,性別等入讀其他MOOC的學生。
  3. 現在,隨著課程的進展,您可以建立新的點陣圖來記錄課程進度。例如,完成了第1周所有講座的學生,完成第1周所有作業的學生。
  4. 現在,基於這些鍵建立實時分析將是一個非常簡單的練習,可以在拖放UI上完成。例如
  • 一位教授想看看有多少學生在第1周(A)觀看講座但沒有完成第1周(B)的作業:操作員:BITOP。操作:A AND(非B)。
  • 完成第1周(A),第2周(B),第3周(C)和第4周(D)的所有作業的學生:操作員:BITOP。操作A和B和C和D.說,這些是通過該課程的人。
  • 所有通過該課程的男學生(M)(如上所述,比如P):操作員:BITOP。操作:M和P.
  • 通過該課程的學生人數:BITCOUNT P.

類似地,可以將任意數量的有趣群組設定為點陣圖,並在其上執行這樣的排列。