Redis 應用-點陣圖

Gundy發表於2019-07-05

系列文章

我們都知道8bit = 1b = $2^{-10}$kb,bitmap就是通過最小的單位bit來進行0或者1的設定,表示某個元素對應的值或者狀態。
一個bit的值,或者是0,或者是1;也就是說一個bit能儲存的最多資訊是2。

點陣圖並不是一種特殊的資料結構,其實本質上是二進位制字串,也可以看做是 byte 陣列。可以使用普通的 get/set 直接獲取和設定整個點陣圖的內容,也可以使用點陣圖操作 getbit/setbit 等將 byte 陣列看成「位陣列」來處理。

點陣圖的優勢:

  1. 基於最小的單位bit進行儲存,所以非常省空間。
  2. 設定時候時間複雜度O(1)、讀取時候時間複雜度O(n),操作是非常快的
  3. 二進位制資料的儲存,進行相關計算的時候非常快
  4. 方便擴容

一般可以在如下場景使用:

  1. 使用者簽到
  2. 使用者線上狀態
  3. 統計活躍使用者
  4. 各種狀態值

常用命令

SETBIT

對 key 所儲存的字串值,設定或清除指定偏移量上的位(bit)。
SETBIT key offset value
offset 引數必須大於或等於 0 ,小於 2^32 (bit 對映被限制在 512 MB 之內)。

GETBIT

對 key 所儲存的字串值,獲取指定偏移量上的位(bit)。
GETBIT key offset

BITCOUNT

計算給定字串中,被設定為 1 的位元位的數量。
BITCOUNT key

BITPOS

返回點陣圖中第一個值為 bit 的二進位制位的位置。
BITPOS key bit [start] [end]

BITOP

對一個或多個儲存二進位制位的字串 key 進行位元操作,並將結果儲存到 destkey 上。
BITOP operation destkey key [key …]
operation 可以是 AND 、 OR 、 NOT 、 XOR 這四種操作中的任意一種
BITOP AND destkey key [key ...] ,對一個或多個 key 求邏輯並,並將結果儲存到 destkey 。

BITFIELD

bitfield 有三個子指令,分別是 get/set/incrby,它們都可以對指定位片段進行讀寫,但是最多隻能處理 64 個連續的位,如果超過 64 位,就得使用多個子指令,bitfield 可以一次執行多個子指令。

適用於各類統計應用

記錄使用者的簽到,每日線上情況等,可以將當天或者當天的偏移量對應的bit位設定為1即可,使用BITCOUNT可以輕鬆統計簽到次數。

還有一種使用比較多的情況,就是設定各類狀態值,例如商城的設定:是否可以評價訂單,是否展示售罄商品,是否正常營業等狀態值可以使用bitmap來儲存

在效能方面,如前面提到的簽到,即使執行 10 年,佔用的空間也只是每個使用者 10*365 位元位(bit),也即是每個使用者 456 位元組。對於這種大小的資料來說, BITCOUNT key [start] [end] 的處理速度就像 GET key 和 INCR key 這種 O(1) 複雜度的操作一樣快。

當然如果你的 bitmap 資料非常大,那麼可以考慮使用以下兩種方法:

  • 將一個大的 bitmap 分散到不同的 key 中,作為小的 bitmap 來處理。使用 Lua 指令碼可以很方便地完成這一工作。
  • 使用 BITCOUNT key [start] [end] 的 start 和 end 引數,每次只對所需的部分位進行計算,然後在進行累加。

本文亦在微信公眾號【小道資訊】釋出,歡迎掃碼關注!
image

相關文章