Redis Bitmap
Bitmap(位圖)是 Redis 提供的一種用于處理二進制位(bit)的特殊數據結構,它基于 String 類型,每個 bit 代表一個布爾值(0 或 1),可以用于存儲大規模的二值狀態數據,如簽到、活躍用戶統計、去重等。
1. Bitmap 基本原理
- Bitmap 本質上是一個二進制數組,每個 bit 僅占 1 位,相比普通的 String 存儲方式(每個字符 8 位),能大幅節省空間。
- Redis 并沒有單獨的數據類型 Bitmap,它是基于
String
結構的。 - 通過 位運算(
SETBIT
、GETBIT
、BITCOUNT
、BITOP
等)高效存取數據。
2. Bitmap 常用命令
(1)SETBIT:設置某一位的值
SETBIT key offset value
key
:鍵名offset
:bit 偏移量(從 0 開始)value
:0
或1
📌 示例
SETBIT user:1001 1 1 # 將 user:1001 的第 1 位設置為 1
SETBIT user:1001 2 0 # 將 user:1001 的第 2 位設置為 0
SETBIT user:1001 5 1 # 將 user:1001 的第 5 位設置為 1
假設 user:1001 初始狀態是:(每個 0 代表 1 bit,總共 32 bit = 4 字節)
00000000 00000000 00000000 00000000
執行:
SETBIT user:1001 5 1 # 將 user:1001 的第 5 位設置為 1
SETBIT user:1001 5 1
結果變成:
00000100 00000000 00000000 00000000
第 5 位(從 0 開始計數,即第 6 個 bit)被設置為 1。
作用:類似于一個布爾數組,可用于表示某個用戶在不同時間點的狀態(如簽到)。
(2)GETBIT:獲取某一位的值
GETBIT key offset
key
:鍵名offset
:bit 偏移量
📌 示例
GETBIT user:1001 1 # 返回 1
GETBIT user:1001 2 # 返回 0
GETBIT user:1001 5 # 返回 1
作用:查詢某個狀態,如某用戶是否簽到。
(3)BITCOUNT:統計 bit 為 1 的個數
BITCOUNT key [start end]
key
:鍵名[start end]
(可選):字節范圍(默認統計整個 key)
📌 示例
BITCOUNT user:1001 # 統計 user:1001 中 bit 為 1 的個數
作用:
- 統計某個用戶的簽到次數
- 統計一段時間內活躍用戶數量
(4)BITOP:對多個 Bitmap 進行位運算
BITOP operation destKey key1 key2 ...
operation
:AND
(與)OR
(或)XOR
(異或)NOT
(非)
destKey
:存儲結果的 keykey1 key2 ...
:參與運算的 key
📌 示例
BITOP AND active_users today yesterday # 統計連續兩天都活躍的用戶
BITOP OR total_active day1 day2 day3 # 統計三天內活躍過的用戶
作用:
- 計算多天簽到的交集、并集
- 統計活躍用戶
3. Bitmap 典型應用
(1)用戶簽到
場景:每個用戶有一個 31 位的 Bitmap(對應 31 天),bit 為 1
表示已簽到,0
表示未簽到。
📌 示例
SETBIT sign:1001:20240301 0 1 # 用戶 1001 在 3 月 1 日簽到
SETBIT sign:1001:20240302 1 1 # 3 月 2 日簽到
SETBIT sign:1001:20240303 2 1 # 3 月 3 日簽到
GETBIT sign:1001:20240303 2 # 查詢 3 月 3 日是否簽到(返回 1)
BITCOUNT sign:1001:202403 # 查詢用戶 1001 3 月簽到次數
(2)統計活躍用戶
場景:每天創建一個 Bitmap,記錄活躍用戶(bit 位置對應用戶 ID)。
📌 示例
SETBIT active:20240301 1001 1 # 用戶 1001 3 月 1 日活躍
SETBIT active:20240301 1002 1 # 用戶 1002 3 月 1 日活躍
SETBIT active:20240302 1002 1 # 用戶 1002 3 月 2 日活躍
BITCOUNT active:20240301 # 統計 3 月 1 日活躍用戶數
BITOP AND active_both active:20240301 active:20240302 # 統計連續兩天活躍的用戶
(3)A/B 測試 & 用戶權限控制
場景:用 Bitmap 存儲用戶是否屬于 A/B 測試組或是否擁有某個權限。
📌 示例
SETBIT experiment:groupA 1001 1 # 用戶 1001 參與 A 組測試
SETBIT experiment:groupB 1002 1 # 用戶 1002 參與 B 組測試
GETBIT experiment:groupA 1001 # 查詢用戶 1001 是否在 A 組
4. Bitmap 優勢
? 節省空間:1 個 bit 僅占 1/8 字節,非常適合存儲大規模用戶數據(如千萬級別用戶簽到情況)。
? 高效查詢:GETBIT
和 SETBIT
操作時間復雜度為 O(1),快速讀寫。
? 支持批量運算:BITCOUNT
、BITOP
等可進行高效統計。
5. Bitmap 限制
? 不支持刪除某個 bit(只能置 0,無法真正刪除)。
? 不支持范圍查詢(需要配合 BITCOUNT
和 GETBIT
)。
? 偏移量有限制(Redis 最大 String
長度約 512MB,即支持 2^32
個 bit)。
6. 總結
功能 | 命令 | 作用 |
---|---|---|
設置 bit | SETBIT key offset value | 設置指定偏移量的 bit |
獲取 bit | GETBIT key offset | 獲取指定偏移量的 bit |
統計 1 的數量 | BITCOUNT key | 統計 key 中 bit 為 1 的個數 |
位運算 | BITOP operation destKey key1 key2 | 對多個 Bitmap 進行 AND/OR/XOR/NOT 運算 |
Bitmap 非常適合用于海量用戶數據的布爾狀態存儲,如簽到、活躍用戶、權限控制等場景。
參考文獻
[1] https://redis.io/docs/latest/develop/data-types/bitmaps/