Redis--位圖BitMap


一、BitMap是什么

通過一個bit位來表示某個元素對應的值或者狀態,其中的key就是對應元素本身,value對應0或1,我們知道8個bit可以組成一個Byte,所以bitmap本身會極大的節省儲存空間。

 

二、Redis中的BitMap

Redis從2.2.0版本開始新增了setbit、getbit、bitcount等幾個bitmap相關命令。雖然是新命令,但是並沒有新增新的數據類型,因為setbit等命令只不過是在set上的擴展。

 

Redis的bitmap讓我們可以實時的進行統計,並且極其節省空間。在模擬1億2千8百萬用戶的模擬環境下,在一台MacBookPro上,典型的統計如“日用戶數”(dailyunique users) 的時間消耗小於50ms, 占用16MB內存。

 

Bitmap是一串連續的2進制數字(0或1),每一位所在的位置為偏移(offset),在bitmap上可執行AND,OR,XOR以及其它位操作。

 

三、Redis中的命令

1、setbit

  語法:setbit key offset value

  描述:

    對key所儲存的字符串值,設置或清除指定偏移量上的位(bit)。

    位的設置或清除取決於 value 參數,可以是 0 也可以是 1 。

    當 key 不存在時,自動生成一個新的字符串值。

    字符串會進行伸展(grown)以確保它可以將 value 保存在指定的偏移量上。當字符串值進行伸展時,空白位置以 0 填充。

  注意:

    offset 參數必須大於或等於 0 ,小於 2^32 (bit 映射被限制在 512 MB 之內)。

    因為 Redis 字符串的大小被限制在 512 兆(megabytes)以內, 所以用戶能夠使用的最大偏移量為 2^29-1(536870911) , 如果你需要使用比這更大的空間, 請使用多個 key。

    當生成一個很長的字符串時, Redis 需要分配內存空間, 該操作有時候可能會造成服務器阻塞(block)。 在2010年出產的Macbook Pro上, 設置偏移量為 536870911(512MB 內存分配)將耗費約 300 毫秒, 設置偏移量為 134217728(128MB 內存分配)將耗費約 80 毫秒, 設置偏移量 33554432(32MB 內存分配)將耗費約 30 毫秒, 設置偏移量為 8388608(8MB 內存分配)將耗費約 8 毫秒。

 

2、getbit

  語法:getbit key offset

  描述:

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

    當 offset 比字符串值的長度大,或者 key 不存在時,返回 0

3、bitcount

  語法:bitcount key [start] [end]

  返回值:被設置為 1 的位的數量

  描述:

    計算給定字符串中,被設置為 1 的比特位的數量

    一般情況下,給定的整個字符串都會被進行計數,通過指定額外的 start 或 end 參數,可以讓計數只在特定的位上進行。

    start 和 end 參數的設置和 GETRANGE key start end 命令類似,都可以使用負數值: 比如 -1表示最后一個字節, -2 表示倒數第二個字節,以此類推。

    不存在的 key 被當成是空字符串來處理,因此對一個不存在的 key 進行 BITCOUNT 操作,結果為 0 。

4、bitpos

5、bitop

  語法:bitop operation destkey key [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 作為輸入。    

  返回值:保存到 destkey 的字符串的長度,和輸入 key 中最長的字符串長度相等

  描述:

    對一個或多個保存二進制位的字符串 key 進行位元操作,並將結果保存到 destkey 上。

  注意:處理不同長度的字符串

    當 BITOP 處理不同長度的字符串時,較短的那個字符串所缺少的部分會被看作 0 。

    空的 key 也被看作是包含 0 的字符串序列。

  

6、bitfield

 

四、應用場景

1、位圖計數統計

位圖計數統計的是bitmap中值為1的位的個數。位圖計數的效率很高,例如,一個bitmap包含10億個位,90%的位都置為1,在一台MacBook Pro上對其做位圖計數需要21.1ms。

例子:日活躍用戶

為了統計今日登錄的用戶數,我們建立了一個bitmap,每一位標識一個用戶ID。當某個用戶訪問我們的網頁或執行了某個操作,就在bitmap中把標識此用戶的位置為1。

每次用戶登錄時會執行一次redis.setbit(daily_active_users, user_id, 1)。將bitmap中對應位置的位置為1,時間復雜度是O(1)。統計bitmap結果顯示有今天有9個用戶登錄。Bitmap的key是daily_active_users,它的值是1011110100100101。

因為日活躍用戶每天都變化,所以需要每天創建一個新的bitmap。我們簡單地把日期添加到key后面,實現了這個功能。例如要統計某一天有多少個用戶訪問,可以把這個bitmap的key設計為daily_active_users:2019-03-27。當用戶訪問進來,我們只是簡單地在bitmap中把標識這個用戶的位置為1,時間復雜度是O(1)。

 

備注:

Redis原生指令參考 http://redisdoc.com/index.html
Redis python客戶端 方法參考 http://redis-py.readthedocs.io/en/latest/#indices-and-tables


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM