Bitmaps


核心知識點:

1.Bitmaps是一種特殊的“數據結構”,實質上是一個字符串,操作單元是位。

2.命令:

  a.setbit:設置值,只能存儲0和1,適用二元判斷類型

  b.getbit:獲取值

  c.bitcount:統計1的數量,可指定范圍

  d.bitop:可取交集、並集、非、異或

  e.bitpos:第一個獲取某種狀態的偏移量

3.Bitmaps並不是任何場合都適合,在某些場合適用會有意想不到的效果。

 

 

1.數據結構模型

現代計算機用二進制(位)作為信息的基礎單位,1個字節等位8位,例如“big”字符串是由3個字節組成,

但實際在計算機存儲時將其用二進制表示,“big”分別對應的ASCII碼分別是98、105、103,

對應的二進制分別是01100010、01101001和01100111,如下圖:

許多開發語言都提供了操作位功能,合理地使用位能夠有效地提高內存使用率和開發效率。

Redis提供了Bitmaps這個“數據結構”,可以實現對位的操作。把數據結構加上引號主要因為:

(1)Bitmaps本身不是一種數據結構,實際上它就是字符串,,但它可以對字符串的位進行操作;

(2)Bitmaps單獨提供了一套命令,所以在Redis中使用Bitmaps和使用字符串的方法不太一樣。

  可以把Bitmaps想象成一個以位為單位的數組,數組的每個單元只能存儲0和1,數組的下標在Bitmaps中叫做偏移量。

 

2.命令

本節將每個獨立用戶是否訪問過網站存放在Bitmaps中,將訪問的用戶記做1,沒有訪問的用戶記做0,用偏移量作為用戶的id。

(1)設置值

setbit key offset value

設置鍵的第offset個位的值(從0算起),假設現在有20個用戶,userid=0,5,11,15,19的用戶對網站進行了訪問,

那么當前Bitmaps初始化結果如圖:

具體操作過程如下,unique:users:2016-04-05代表2016-04-05這天的獨立訪問用戶的Bitmaps:

127.0.0.1:6379> setbit unique:users:2016-04-05 0 1
(integer) 0
127.0.0.1:6379> setbit unique:users:2016-04-05 5 1
(integer) 0
127.0.0.1:6379> setbit unique:users:2016-04-05 11 1
(integer) 0
127.0.0.1:6379> setbit unique:users:2016-04-05 15 1
(integer) 0
127.0.0.1:6379> setbit unique:users:2016-04-05 19 1
(integer) 0

很多應用的用戶id以一個指定的數字(例如10000)開頭,直接將用戶id和Birmaps的偏移量對應勢必會造成一定的浪費,

通常的做法是每次做setbit操作時將用戶id減去這個指定數字。

在第一次初始化Bitmaps時,如果偏移量非常大,那么整個初始化過程執行會比較慢,可能會造成Redis阻塞。

 

(2)獲取值

getbit key offset

獲取鍵的第offset位的值(從0開始計算),如果返回0代表沒有訪問,返回1代表訪問過。

127.0.0.1:6379> getbit unique:users:2016-04-05 8
(integer) 0
127.0.0.1:6379> getbit unique:users:2016-04-05 5
(integer) 1
127.0.0.1:6379> getbit unique:users:2016-04-05 1000
(integer) 0
#不存在1000,自然返回0

 

(3)獲取Bitmaps指定范圍值為1的個數

bitcount key [start] [end]
127.0.0.1:6379> bitcount unique:users:2016-04-05
(integer) 5
127.0.0.1:6379> bitcount unique:users:2016-04-05 10 20
(integer) 0
127.0.0.1:6379> bitcount unique:users:2016-04-05 1 3
(integer) 3
#start和and代表字節數,一個字節8位,1到3個字節就是索引在8到23之間

 

(4)Bitmaps間的運算

bitop op destkey key [key ...]

bitop是一個復合操作,它可以做多個Bitmaps的and(交集)、or(並集)、not(非)、xor(異或)操作,並將結果保存在destkey中。

下面有該網站連續2天客戶訪問的Bitmaps記錄:

下面操作計算兩天都訪問網站的用戶數:

127.0.0.1:6379> bitop and unique:users:and:2016-04-03_04 unique:users:2016-04-03 unique:users:2016-04-04
(integer) 2
127.0.0.1:6379> bitcount unique:users:and:2016-04-03_04
(integer) 2

下面操作計算兩天中至少有一天訪問網站的用戶數:

127.0.0.1:6379> bitop or unique:users:or:2016-04-03_04 unique:users:2016-04-03 unique:users:2016-04-04
(integer) 2
127.0.0.1:6379> bitcount unique:users:or:2016-04-03_04
(integer) 6

 

(5)計算Bitmaps中第一個值為tergetBit的偏移量

bitpos key targetBit [start] [end]

下面操作計算2016-04-03這一天當前訪問網站的最小用戶id:

127.0.0.1:6379> bitpos unique:users:2016-04-03 1
(integer) 0  #索引為1的用戶最先訪問

除此之外,bitpos還可以指定start和end,分別代表起始字節和結束字節:

127.0.0.1:6379> bitpos unique:users:2016-04-04 1 1 2
(integer) 9

 

3.Bitmaps性能分析

假設網站有1億用戶,每天獨立訪問的用戶是5000萬,如果每天用集合類型和Bitmaps分別存儲活躍用戶。

很容易看出,在這種情況下Bitmaps能節省很多內存空間,尤其隨着時間推移比較客觀。

但是Bitmaps並不是萬金油,當該網站每天訪問的用戶很少時,Bitmaps就有點不合時宜了。

注釋:由於有5000萬活躍用戶,每個用戶一個id,這就需要8位數字表示,每個數字一個字節因此就是64位。

 


免責聲明!

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



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