Redis點陣圖Bitmaps詳解
技術標籤:redis
概念
-
Redis
提供的Bitmaps這個“資料結構”可以實現對位的操作。Bitmaps本身不是一種資料結構,實際上就是字串,但是它可以對字串的位進行操作。 -
可以把Bitmaps想象成一個以位為單位的陣列,陣列中的每個單元只能存0或者1,陣列的下標在bitmaps中叫做偏移量。
-
單個bitmaps的最大長度是
512MB
,即2^32個位元位。
例如字串A 一個位元組,對應的ASCII碼是65,對應的二進位制就是01000001,Bitmaps就是對A的二進位制位進行操作。
命令
SETBIT
SETBIT key offset value
summary: Sets or clears the bit at offset in the string value stored at key
設定鍵的第offset個位的值,value只有0和1兩個值
字串A在位陣列的 1和7兩個位置是1(從0算起)
127.0.0.1:6379[1]> setbit k1 1 1
(integer) 0
127.0.0.1:6379[1]> setbit k1 7 1
(integer) 0
127.0.0.1:6379[1]> get k1
"A"
127.0.0.1:6379[1]> strlen k1
(integer) 1
對 位1和7設定成1,可以得到字串A,這時k1只有8位,1個位元組,所以長度為1,接下來再對k1進行如下設定
127.0.0.1:6379[1]> setbit k1 9 1
(integer) 0
127.0.0.1:6379[1]> setbit k1 14 1
(integer) 0
127.0.0.1:6379[1]> get k1
"AB"
127.0.0.1:6379[1]> strlen k1
(integer) 2
這時k1
的值是如下圖,佔2個位元組
GETBIT
GETBIT key offset
summary: Returns the bit value at offset in the string value stored at key
獲取鍵的第offset位的值
127.0.0.1:6379[1]> getbit k1 1
(integer) 1
127.0.0.1:6379[1]> getbit k1 2
(integer) 0
BITCOUNT
BITCOUNT key [start end]
summary: Count set bits in a string
獲取指定範圍值為1的個數,其中start和end代表起始和結束位元組數
127.0.0.1:6379[1]> bitcount k1 0 0
(integer) 2
127.0.0.1:6379[1]> bitcount k1 1 1
(integer) 2
127.0.0.1:6379[1]> bitcount k1 0 1
(integer) 4
BITPOS
BITPOS key bit [start] [end]
summary: Find first bit set or clear in a string
計算Bitmaps中的第一值為0或者1的偏移量,start和end分別代表起始位元組和結束位元組
127.0.0.1:6379[1]> bitpos k1 1 0 0
(integer) 1
127.0.0.1:6379[1]> bitpos k1 1 1 1
(integer) 9
127.0.0.1:6379[1]> bitpos k1 0 1 1
(integer) 8
對比上圖k1
值的位陣列進行驗證
BITOP
BITOP operation destkey key [key ...]
summary: Perform bitwise operations between strings
bitop
是一個複合操作,可以做多個Bitmaps的and
、or
、not
、xor
操作。
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
設定k2
01000001
127.0.0.1:6379[1]> setbit k2 1 1
(integer) 0
127.0.0.1:6379[1]> setbit k2 7 1
(integer) 0
127.0.0.1:6379[1]> get k2
"A"
設定k3
01000010
127.0.0.1:6379[1]> setbit k3 1 1
(integer) 0
127.0.0.1:6379[1]> setbit k3 6 1
(integer) 0
127.0.0.1:6379[1]> get k3
"B"
AND
127.0.0.1:6379[1]> bitop and anddest k2 k3
(integer) 1
127.0.0.1:6379[1]> get anddest
"@"
k2
01000001 和 k3
01000010做與運算(有0為0,全1為1) 結果 01000000 對應的ASCII碼是@
OR
127.0.0.1:6379[1]> bitop or ordest k2 k3
(integer) 1
127.0.0.1:6379[1]> get ordest
"C"
k2
01000001 和 k3
01000010做或運算(有1為1全0為0) 結果 01000011 對應的ASCII碼是C
XOR
127.0.0.1:6379[1]> bitop xor xordest k2 k3
(integer) 1
127.0.0.1:6379[1]> get xordest
"\x03"
k2
01000001 和 k3
01000010做異或運算(相同為0,不同為1) 結果 00000011 對應的十六進位制\x03 十進位制下3
NOT
127.0.0.1:6379[1]> bitop not notdest k2
(integer) 1
127.0.0.1:6379[1]> get notdest
"\xbe"
對k2
01000001 做非運算(非0則1,非1則0) 結果是 10111110 對應的十六進位制\xbe
BITFIELD
BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]
summary: Perform arbitrary bitfield integer operations on strings
redis3.2
後新增了一個bitfield
命令,可以一次對多個位進行操作.這個指令有三個子指令,get,set,incrby
,都可以對指定位片段進行讀寫,但最大支援 64 位長的有符號整數以及 63 位長的無符號整數, 其中無符號整數的 63 位長度限制是由於 Redis
協議目前還無法返回 64 位長的無符號整數而導致的。。
BITFIELD
命令支援的子命令:
GET <type> <offset>
—— 返回指定的二進位制位範圍。SET <type> <offset> <value>
—— 對指定的二進位制位範圍進行設定,並返回它的舊值。INCRBY <type> <offset> <increment>
—— 對指定的二進位制位範圍執行加法操作,並返回它的舊值。使用者可以通過向increment
引數傳入負值來實現相應的減法操作。
除了以上三個子命令之外, 還有一個子命令, 它可以改變之後執行的 INCRBY
子命令在發生溢位情況時的行為:
OVERFLOW [WRAP|SAT|FAIL]
當被設定的二進位制位範圍值為整數時, 使用者可以在型別引數的前面新增 i
來表示有符號整數, 或者使用 u
來表示無符號整數。 比如說, 我們可以使用 u8
來表示 8 位長的無符號整數, 也可以使用 i16
來表示 16 位長的有符號整數。
127.0.0.1:6379[1]> set k4 A
OK
#A對應的二進位制 01000001
#從第1個位開始讀取4個位 0100 結果為無符號數(u)
127.0.0.1:6379[1]> bitfield k4 get u4 0
1) (integer) 4
#從第2個位開始讀取2個位 10 結果為無符號數(u)
127.0.0.1:6379[1]> bitfield k4 get u2 1
1) (integer) 2
#從第0個位開始讀取3個位 010 結果為有符號數(i)
127.0.0.1:6379[1]> bitfield k4 get i3 0
1) (integer) 2
#從第1個位開始讀取5個位 10000 結果為有符號數(i) 首位是1代表負數,對10000減1 -> 01111 取反 -> 10000 十進位制下是16,由於符號位是1,所以結果是-16
127.0.0.1:6379[1]> bitfield k4 get i5 1
1) (integer) -16
二進位制位和位置偏移量
在二進位制位範圍命令中, 使用者有兩種方法來設定偏移量:
- 如果使用者給定的是一個沒有任何字首的數字, 那麼這個數字指示的就是字串以零為開始(zero-base)的偏移量。
- 另一方面, 如果使用者給定的是一個帶有
#
字首的偏移量, 那麼命令將使用這個偏移量與被設定的數字型別的位長度相乘, 從而計算出真正的偏移量。
127.0.0.1:6379[1]> BITFIELD k5 SET i8 #0 100
1) (integer) 0
127.0.0.1:6379[1]> BITFIELD k5 SET i8 #1 200
1) (integer) 0
# 01100100 11001000
命令會把 k5
鍵裡面, 第一個 i8
長度的二進位制位的值設定為 100
, 並把第二個 i8
長度的二進位制位的值設定為 200
。 當我們把一個字串鍵當成陣列來使用, 並且陣列中儲存的都是同等長度的整數時, 使用 #
字首可以讓我們免去手動計算被設定二進位制位所在位置的麻煩。
應用
統計使用者登入天數
構建長度為天數365的位陣列,哪天登入過,設定value為1,這樣每個使用者最多佔用46個位元組
127.0.0.1:6379[1]> setbit jack 1 1 #第2天登入過
(integer) 0
127.0.0.1:6379[1]> setbit jack 8 1 #第9天登入過
(integer) 0
127.0.0.1:6379[1]> setbit jack 364 1 #第365天登入過
(integer) 0
127.0.0.1:6379[1]> strlen jack
(integer) 46
127.0.0.1:6379[1]> bitcount jack #登入的天數
(integer) 3
統計每天的活躍使用者數量
位陣列,每一位代表使用者的ID
127.0.0.1:6379[1]> setbit 2020-11-11 1 1 #使用者ID為1使用者活躍
(integer) 0
127.0.0.1:6379[1]> setbit 2020-11-11 30 1 #使用者ID為30使用者活躍
(integer) 0
127.0.0.1:6379[1]> setbit 2020-11-11 184 1 #使用者ID為184使用者活躍
(integer) 0
127.0.0.1:6379[1]> bitcount 2020-11-11 #統計2020-11-11的活躍量
(integer) 3
像簽到、點贊、評論數都可以用Bitmaps來實現