一文搞懂redis的bitmap

本篇文章給大家帶來了關于redis的相關知識,其中主要介紹了bitmap問題,redis 為我們提供了位圖這一數據結構,位圖數據結構其實并不是一個全新的玩意,我們可以簡單的認為就是個數組,只是里面的內容只能為0或1而已,希望對大家有幫助。

一文搞懂redis的bitmap

推薦學習:redis

1.位圖簡介

如果我們需要記錄某一用戶在一年中每天是否有登錄我們的系統這一需求該如何完成呢?如果使用KV存儲,每個用戶需要記錄365個,當用戶量上億時,這所需要的存儲空間是驚人的。

redis 為我們提供了位圖這一數據結構,每個用戶每天的登錄記錄只占據一位,365天就是365位,僅僅需要46字節就可存儲,極大地節約了存儲空間。

一文搞懂redis的bitmap

位圖數據結構其實并不是一個全新的玩意,我們可以簡單的認為就是個數組,只是里面的內容只能為0或1而已(二進制位數組)。

2.命令實戰

Redis提供了SETBIT、GETBIT、BITCOUNT、BITOP四個常用命令用于處理二進制位數組。

  • SETBIT:為位數組指定偏移量上的二進制位設置值,偏移量從0開始計數,二進制位的值只能為0或1。返回原位置值。
  • GETBIT:獲取指定偏移量上二進制位的值。
  • BITCOUNT:統計位數組中值為1的二進制位數量。
  • BITOP:對多個位數組進行按位與、或、異或運算。
127.0.0.1:6379> SETBIT first 0 1    # 0000 0001 (integer) 0 127.0.0.1:6379> SETBIT first 3 1    # 0000 1001 (integer) 0 127.0.0.1:6379> SETBIT first 0 0    # 0000 1000 (integer) 1  127.0.0.1:6379> GETBIT first 0 (integer) 0 127.0.0.1:6379> GETBIT first 3 (integer) 1  127.0.0.1:6379> BITCOUNT first      # 0000 1000 (integer) 1 127.0.0.1:6379> SETBIT first 0 1    # 0000 1001 (integer) 0 127.0.0.1:6379> BITCOUNT first      # 0000 1001 (integer) 2 127.0.0.1:6379> SETBIT first 1 1    # 0000 1011 (integer) 0 127.0.0.1:6379> BITCOUNT first      # 0000 1011 (integer) 3  127.0.0.1:6379> SETBIT x 3 1         (integer) 0 127.0.0.1:6379> SETBIT x 1 1         (integer) 0 127.0.0.1:6379> SETBIT x 0 1        # 0000 1011 (integer) 0 127.0.0.1:6379> SETBIT y 2 1         (integer) 0 127.0.0.1:6379> SETBIT y 1 1        # 0000 0110 (integer) 0 127.0.0.1:6379> SETBIT z 2 1         (integer) 0 127.0.0.1:6379> SETBIT z 0 1        # 0000 0101 (integer) 0  127.0.0.1:6379> BITOP AND andRes x y z    #0000 0000 (integer) 1 127.0.0.1:6379> BITOP OR orRes x y z      #0000 1111 (integer) 1 127.0.0.1:6379> BITOP XOR x y z           #0000 1000 (integer) 1  # 對給定的位數組進行按位取反 127.0.0.1:6379> SETBIT value 0 1 (integer) 0 127.0.0.1:6379> SETBIT value 3 1            #0000 1001 (integer) 0 127.0.0.1:6379> BITOP NOT notValue value    #1111 0110 (integer) 1

3.BitMap源碼分析

3.1 數據結構

如下展示了一個用 SDS 表示的一字節(8位)長的位圖:

一文搞懂redis的bitmap

擴展:Redis 中的每個對象都是有一個 redisObject 結構表示的。

typedef struct redisObject { // 類型 unsigned type:4; // 編碼 unsigned encoding:4; unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */ // 引用計數 int refcount; // 執行底層實現的數據結構的指針 void *ptr; } robj;