Redis學習筆記(6)- Bitmap(位圖)

1、簡介

  位圖不是一個真實的數據類型,而是定義在字符串類型上的面向位的操作的集合。由於字符串類型是二進制安全的二進制大對象,並且最大長度是 512MB,適合於設置 2^32個不同的位。
  位圖的最大優勢是有時是一種非常顯著的節省空間來存儲信息的方式。例如,比如統計用戶是否在線,可以通過將數組中的每個二進制位與用戶 ID 進行一一對應, 我們可以使用位圖去記錄每個用戶是否在線。
  簡而言之,位圖操作是用來操作比特位的,其優點是節省內存空間。在記錄用戶是否在線的功能中,一個bit位對應一個用戶,bit位的0/1可以表示用戶是否在線,這樣就可以通過一個bit位來表示一個用戶是否在線了。

2、Bitmap(位圖)命令
  1. SETBIT
    語法: SETBIT key offset value
    時間複雜度: O(1)
    功能: 對 key 所儲存的字符串值,設置或清除指定偏移量上的位(bit)。
    返回值: 指定偏移量原來儲存的位。
      位的設置或清除取決於 value 參數,可以是 0 也可以是 1 。
      當 key 不存在時,自動生成一個新的字符串值。
      字符串會進行伸展(grown)以確保它可以將 value 保存在指定的偏移量上。當字符串值進行伸展時,空白位置以 0 填充。
      offset 參數必須大於或等於 0 ,小於 2^32 (bit 映射被限制在 512 MB 之內)。

對使用大的 offset 的 SETBIT 操作來說,內存分配可能造成 Redis 服務器被阻塞。具體參考 SETRANGE key offset value 命令,warning(警告)部分。
在這裏插入圖片描述

  1. GETBIT
    語法: GETBIT key offset
    時間複雜度: O(1)
    功能: 對 key 所儲存的字符串值,獲取指定偏移量上的位(bit)。當 offset 比字符串值的長度大,或者 key 不存在時,返回 0 。
    返回值: 字符串值指定偏移量上的位(bit)。
    在這裏插入圖片描述
  2. BITCOUNT
    語法: BITCOUNT key [start] [end]
    時間複雜度: O(N)
    功能: 計算給定字符串中,被設置爲 1 的比特位的數量。
    返回值: 被設置爲 1 的位的數量。

  一般情況下,給定的整個字符串都會被進行計數,通過指定額外的 start 或 end 參數,可以讓計數只在特定的位上進行。
  start 和 end 參數的設置和 GETRANGE key start end 命令類似,都可以使用負數值: 比如 -1 表示最後一個字節, -2 表示倒數第二個字節,以此類推。
  不存在的 key 被當成是空字符串來處理,因此對一個不存在的 key 進行 BITCOUNT 操作,結果爲 0 。
在這裏插入圖片描述

  1. BITPOS
    語法: BITPOS key bit [start] [end]
    時間複雜度: O(N),其中 N 爲位圖包含的二進制位數量
    功能: 返回位圖中第一個值爲 bit 的二進制位的位置。在默認情況下, 命令將檢測整個位圖, 但用戶也可以通過可選的 start 參數和 end 參數指定要檢測的範圍。
    返回值: 整數回覆。
    在這裏插入圖片描述

  2. BITOP
    語法: BITOP operation destkey key [key …]
    時間複雜度: O(N)
    功能: 對一個或多個保存二進制位的字符串 key 進行位元操作,並將結果保存到 destkey 上。
    返回值: 保存到 destkey 的字符串的長度,和輸入 key 中最長的字符串長度相等。

  operation 可以是 AND 、 OR 、 NOT 、 XOR 這四種操作中的任意一種:

  • BITOP AND destkey key [key …] ,對一個或多個 key 求邏輯並,並將結果保存到 destkey 。

  • BITOP OR destkey key [key …] ,對一個或多個 key 求邏輯或,並將結果保存到 destkey 。

  • BITOP XOR destkey key [key …] ,對一個或多個 key 求邏輯異或,並將結果保存到 destkey 。

  • BITOP NOT destkey key ,對給定 key 求邏輯非,並將結果保存到 destkey 。

  除了 NOT 操作之外,其他操作都可以接受一個或多個 key 作爲輸入。

處理不同長度的字符串
  當 BITOP 處理不同長度的字符串時,較短的那個字符串所缺少的部分會被看作 0 。空的 key 也被看作是包含 0 的字符串序列。

BITOP 的複雜度爲 O(N) ,當處理大型矩陣(matrix)或者進行大數據量的統計時,最好將任務指派到附屬節點(slave)進行,避免阻塞主節點。
在這裏插入圖片描述

  1. BITFIELD
    語法: BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]
    時間複雜度: 每個子命令的複雜度爲 O(1)
    功能: BITFIELD 命令可以將一個 Redis 字符串看作是一個由二進制位組成的數組, 並對這個數組中儲存的長度不同的整數進行訪問 (被儲存的整數無需進行對齊)。 換句話說, 通過這個命令, 用戶可以執行諸如 “對偏移量 1234 上的 5 位長有符號整數進行設置”、 “獲取偏移量 4567 上的 31 位長無符號整數”等操作。 此外, BITFIELD 命令還可以對指定的整數執行加法操作和減法操作, 並且這些操作可以通過設置妥善地處理計算時出現的溢出情況。
    返回值: BITFIELD 命令的返回值是一個數組, 數組中的每個元素對應一個被執行的子命令。 需要注意的是, OVERFLOW 子命令本身並不產生任何回覆。

  BITFIELD 命令的作用在於它能夠將很多小的整數儲存到一個長度較大的位圖中, 又或者將一個非常龐大的鍵分割爲多個較小的鍵來進行儲存, 從而非常高效地使用內存, 使得 Redis 能夠得到更多不同的應用 —— 特別是在實時分析領域: BITFIELD 能夠以指定的方式對計算溢出進行控制的能力, 使得它可以被應用於這一領域。

  該命令較複雜,具體可以參考《Redis命令參考 - BITFIELD》
在這裏插入圖片描述

3、Bitmap(位圖)應用

  通過Bitmap(位圖)來統計在線用戶,既可以獲取在線用戶名單, 又可以儘量減少內存消耗的。
  Redis 的位圖就是一個由二進制位組成的數組, 可以通過將數組中的每個二進制位與用戶 ID 進行一一對應, 我們可以使用位圖去記錄每個用戶是否在線。
  當一個用戶上線時, 我們就使用 SETBIT 命令, 將這個用戶對應的二進制位設置爲 1 :

# 此處的 user_id 必須爲數字,因爲它會被用作索引
SETBIT "online_users" <user_id> 1

  通過使用 GETBIT 命令去檢查一個二進制位的值是否爲 1 , 我們可以知道指定的用戶是否在線:

GETBIT "online_users" <user_id>

  而通過 BITCOUNT 命令, 我們可以統計出位圖中有多少個二進制位被設置成了 1 , 也即是有多少個用戶在線:

BITCOUNT "online_users"

  跟集合一樣, 用戶也能夠對多個位圖進行聚合計算 —— 通過 BITOP 命令, 用戶可以對一個或多個位圖執行邏輯並、邏輯或、邏輯異或或者邏輯非操作:

# 計算出 7 天都在線的用戶
BITOP "AND" "7_days_both_online_users" "day_1_online_users" "day_2_online_users" ... "day_7_online_users"
# 計算出 7 在的在線用戶總人數
BITOP "OR" "7_days_total_online_users" "day_1_online_users" "day_2_online_users" ... "day_7_online_users"
# 計算出兩天當中只有其中一天在線的用戶
BITOP "XOR" "only_one_day_online" "day_1_online_users" "day_2_online_users"

  和HyperLogLog相比,位圖節約內存的效果不及 HyperLogLog 那麼顯著, 但是使用位圖可以準確地判斷一個用戶是否上線, 並且能夠像集合和有序集合一樣, 對在線用戶名單進行聚合計算。 因此對於想要儘量節約內存, 但又需要準確地知道用戶是否在線, 又或者需要對用戶的在線名單進行聚合計算的應用來說, 使用位圖可以說是最佳之選。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章