前言
Bitmap實際上并不是一種數(shù)據(jù)類型,而是定義在String類型上的面向位的操作。因為String是二進制安全的并且最大長度為512MB,所以String可以建立2^32個不同的位。位操作被分為兩種:
- 常數(shù)時間的單獨一個位的操作税弃,比如設(shè)置某個位的值為1或者0,或者或者某個位的值
- 對一組bit位的操作,例如在給定的位范圍內(nèi)計算被設(shè)置的bit數(shù)量(如人口統(tǒng)計)
Bitmap最大的一個優(yōu)點是當(dāng)存儲信息時可以節(jié)省極大的空間骏令。例如一個系統(tǒng)中的用戶ID由遞增的ID表示,只需使用512MB的內(nèi)存垄提,就可以記住40億用戶的單比特信息(例如榔袋,知道用戶是否想收到通訊)。
Bitmap使用SETBIT
和GETBIT
命令設(shè)置和獲取位的值:
> SETBIT key 10 1
> GETBIT key 10
SETBIT
命令第一個參數(shù)表示需要被設(shè)置的位铡俐,第二個參數(shù)表示需要設(shè)置的值(1或者0)凰兑。需要注意的是,當(dāng)被設(shè)置的位超過字符串當(dāng)前的長度時审丘,SETBIT
命令將會自動增加字符串的長度吏够。GETBIT
返回指定位上的值,對于超過字符串當(dāng)前長度范圍的位,總是被視為0锅知。
Bitmap有三個命令是基于對一組位進行操作的命令:
-
BITOP
:在不同字符串之間執(zhí)行逐位的操作播急,Redis提供的操作有的:AND
,OR
售睹,XOR
-
BITCOUNT
:統(tǒng)計值為1的位數(shù) -
BITPOS
:獲取第一個被設(shè)置位0或者1的位
BITPOS
和BITCOUNT
都可以對字符串的字節(jié)范圍進行操作桩警,Bitmap的常見使用場景有:
- 各種實時分析
- 存儲與對象ID相關(guān)的布爾信息
比如想統(tǒng)計網(wǎng)站最長的用戶連續(xù)訪問天數(shù),可以使用Bitmap昌妹,每個位的值作為該天是否訪問網(wǎng)站的標(biāo)志(第一位表示第一天捶枢,第二位表示第二天,以此類推)捺宗,每當(dāng)用戶訪問網(wǎng)站時可以使用SETBIT
設(shè)置該天對應(yīng)的位為1柱蟀,最后統(tǒng)計連續(xù)設(shè)置為1的位的數(shù)量即可。使用BITCOUNT
可以統(tǒng)計出用戶訪問網(wǎng)站的天數(shù)蚜厉,使用BITPOS
即可統(tǒng)計出最長的連續(xù)訪問天數(shù)长已。為了分片數(shù)據(jù)集,最好避免使用大鍵昼牛,可以讓每個鍵存儲M個位术瓮,將(位數(shù)/M)的值與鍵名關(guān)聯(lián),將(位數(shù)%M)可以獲取位數(shù)處于鍵內(nèi)的位置贰健。
下面是Bitmap相關(guān)命令胞四。
BITCOUNT key [ start end [ BYTE | BIT]]
- 可用版本: v2.6.0開始
-
歷史: 從v7.0.0開始增加
BYTE|BIT
選項 - 時間復(fù)雜度: O(N)
-
解釋: 計算字符串中被設(shè)置為1的位數(shù)。默認(rèn)情況下伶椿,字符串中所有的字節(jié)都會被檢查辜伟,可以通過
start
和end
選項指定命令僅執(zhí)行于字符串的某個范圍內(nèi)(start
和end
可以為正數(shù)或者負(fù)數(shù),整數(shù)表示以從頭到尾的順序計算脊另,反之負(fù)數(shù)表示叢尾到頭的順序計算导狡,-1表示最后一位,-2表示倒數(shù)第二位等等)偎痛。不存在的key被視為空字符串旱捧,命令將返回0。默認(rèn)情況下踩麦,start
和end
選項指明的是字節(jié)范圍枚赡,調(diào)用方可以通過BIT
選項來指明位范圍。 - 返回值: Integer(整型)谓谦,返回被設(shè)置為1的位數(shù)贫橙。
BITFIELD key GET encoding offset | [OVERFLOW WRAP | SAT | FAIL] SET encoding offset value | INCRBY encoding offset increment [ GET encoding offset | [OVERFLOW WRAP | SAT | FAIL] SET encoding offset value | INCRBY encoding offset increment ...]
可用版本: v3.2.0開始
時間復(fù)雜度: 對于每個子命令的時間復(fù)雜度為O(1)
-
解釋: 此命令將Redis字符串視為一個bit數(shù)組,可以處理不同比特寬度的特定整數(shù)字段和任意非(必要)對齊的偏移反粥,例如可以將偏移量為1234的有符號5位整數(shù)設(shè)置為一個特定的值料皇,從偏移量4567檢索到一個31位無符號整數(shù)谓松,同樣此命令也可以處理指定偏移量整數(shù)的增量和減量,提供用戶可以配置的保證和明確指定的上溢和下溢行為践剂。
BITFIELD
可以在一次調(diào)用中使用多個位字段鬼譬,并返滬一個回復(fù)數(shù)組,每個數(shù)組對應(yīng)相應(yīng)順序的操作結(jié)果逊脯。BITFIELD
支持的子命令有:- SET encoding offset value 設(shè)置指定位字段同時返回這些字段的舊值
- GET encoding offset 返回指定位字段的值
- INCRBY encoding offset increment 增加或者減少(如果給定的增量為負(fù)數(shù))指定位字段同時返回操作后的新值
-
OVERFLOW [WARP|SAT|FAIL] 此子命令通過設(shè)置溢出行為來改變連續(xù)的
INCRBY
和SET
子命令溢出時的調(diào)用行為优质,需要注意的是OVERFLOW
只影響子命令列表中位于其之后的SET
和INCRBY
子命令,直到下一個OVERFLOW
語句军洼。-
WARP: 針對有符號和無符號的整數(shù)巩螃,在無符號整數(shù)的情況下,
WARP
就像對整數(shù)所能包含的最大值進行模數(shù)化操作(C的標(biāo)準(zhǔn)行為)匕争。對于有符號的整數(shù)避乏,WARP
意味著溢出是朝著最負(fù)的值重新開始的,而溢出是朝著最正的值重新開始的甘桑,如果一個i8整數(shù)被設(shè)置為127拍皮,將其遞增1會產(chǎn)生-128 - SAT: 使用飽和算法,在下溢時跑杭,值被設(shè)置為最小的整數(shù)值铆帽,而在上溢時,則設(shè)置為最大的整數(shù)值德谅。例如爹橱,一個i8整數(shù)從值120開始增量為10,將導(dǎo)致值為127窄做,進一步增量將始終保持在127愧驱。同樣的情況也發(fā)生在下溢上,但是數(shù)值會被封鎖在最負(fù)的數(shù)值上
- FAIL: 不會對檢測到的上溢或下溢執(zhí)行任何操作椭盏。相應(yīng)的返回值設(shè)置為NULL以向調(diào)用者發(fā)出條件信號
-
WARP: 針對有符號和無符號的整數(shù)巩螃,在無符號整數(shù)的情況下,
整數(shù)編碼(encoding)的可選值有:i表示有符號整數(shù)组砚,
i16
表示有符號的16位整數(shù);u表示無符號整數(shù)庸汗,u8
表示無符號的8位整數(shù)惫确,有符號整數(shù)支持的編碼最多為64位手报,無符號整數(shù)最多支持63位蚯舱。無符號整數(shù)的這種限制是由于目前Redis協(xié)議無法返回64位無符號整數(shù)作為回復(fù)。
命令使用實例掩蛤;> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1 1) (integer) 1 2) (integer) 1 > BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1 1) (integer) 2 2) (integer) 2 > BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1 1) (integer) 3 2) (integer) 3 > BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1 1) (integer) 0 2) (integer) 3
返回值: Array(數(shù)組)枉昏,返回每個子命令的操作結(jié)果,結(jié)果順序與子命令順序一致揍鸟。
OVERFLOW
返回值為nil
BITFIELD_RO key GET encoding offset [ encoding offset ...]
- 可用版本: v6.2.0開始
- 時間復(fù)雜度: O(N)兄裂,N為子命令數(shù)量
-
解釋:
BITFIELD
命令的只讀形式句旱,不同的是BITFIELD_RO
只接受GET
子命令,并且可以安全在只讀副本集中晰奖。 - 返回值: Array(數(shù)組)谈撒,返回每個子命令的操作結(jié)果,結(jié)果順序與子命令順序一致
BITOP operation destkey key [key ...]
- 可用版本: v2.6.0開始
- 時間復(fù)雜度: O(N)
-
解釋: 在多個key之間執(zhí)行逐位地進行位操作匾南,并且將結(jié)果存儲進
destkey
中啃匿,BITOP
支持的位操作命令有:AND
、OR
蛆楞、XOR
溯乒、NOT
(其中NOT
操作只接受一個key):- BITOP AND destkey srckey1 srckey2 srckey3 ... srckeyN
- BITOP OR destkey srckey1 srckey2 srckey3 ... srckeyN
- BITOP XOR destkey srckey1 srckey2 srckey3 ... srckeyN
- BITOP NOT destkey srckey
命令執(zhí)行時,對于長度不相同的字符串來說豹爹,Redis將會用0進行填充裆悄,使其長度達到最長字符串的長度;同時對于不存在的key臂聋,Redis也將其視為全為0的字符串
- 返回值: Integer(整型)光稼,返回存儲在目標(biāo)鍵中的字符串長度,該字符串長度等于輸入鍵中對應(yīng)的字符串中長度最長的值
BITPOS key bit [ start [ end [ BYTE | BIT]]]
- 可用版本: v2.8.7開始
-
歷史: 從v7.0.0開始增加
BYTE
和BIT
選項 - 時間復(fù)雜度: O(N)
-
解釋: 返回字符串中第一個被設(shè)置為0或者1的位的位置逻住。此命令將字符串視為從左到右的位數(shù)組钟哥,其中第一個字節(jié)的最高有效位在位置0,第二個字節(jié)的最高有效位在位置8瞎访,依此類推腻贰。
默認(rèn)情況下,字符串中包含的所有字節(jié)都將被檢查扒秸。調(diào)用方可以通過參數(shù)start
和end
播演,指明只在指定的區(qū)間內(nèi)查找位(也可以只傳遞start,操作將假定end是字符串的最后一個字節(jié))伴奥。默認(rèn)情況下写烤,范圍被解釋為一個字節(jié)的范圍,而不是一個比特的范圍拾徙,所以start=0和end=2意味著查看前三個字節(jié)洲炊;可以使用可選的BIT
修飾符來指定應(yīng)將范圍解釋為位范圍,當(dāng)使用BIT
選項時尼啡,start=0和end=2表示看前三位暂衡。
不存在的key將被視為空字符串;start
和end
的值既可以是正數(shù)也可以是負(fù)數(shù)崖瞭,正數(shù)表示從正序狂巢,反之為倒序。 - 返回值: Integer(整型)书聚,返回指定范圍內(nèi)第一個0或者1所在的位或者字節(jié)數(shù)唧领。
GETBIT key offset
- 可用版本: v2.2.0開始
- 時間復(fù)雜度: O(1)
-
解釋: 返回存儲在位置
offset
處的位值藻雌。當(dāng)offset
超過字符串長度時,超出部分的字符串被假定為一個位值為0的連續(xù)空間斩个;當(dāng)key不存在時胯杭,它被假定為一個空字符串甘邀,因此偏移量總是超出范圍练俐,并且該值也被假定為一個以0填充的連續(xù)空間 -
返回值: Integer(整型),返回存儲在位置
offset
處的值
SETBIT key offset value
- 可用版本: v2.2.0開始
- 時間復(fù)雜度: O(1)
-
解釋: 設(shè)置或者清除
offset
處的位值激蹲,設(shè)置的值可以是0或者1腔呜。當(dāng)key不存在時叁温,將會創(chuàng)建一個新的字符串值,字符串的長度會自動增長(填充0)以確保它可以達到偏移量處的位置核畴。偏移量參數(shù)必須大于或等于0膝但,并且小于 2^32(因為Redis字符串長度限制位512MB) -
返回值: Integer(整型),返回存儲在
offset
的舊值