共計 2575 個字符,預(yù)計需要花費 7 分鐘才能閱讀完成。
本篇內(nèi)容主要講解“Redis 中的 bitmap 是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學(xué)習(xí)“Redis 中的 bitmap 是什么”吧!
Redis 的位圖(bitmap)是由多個二進制位組成的數(shù)組,數(shù)組中的每個二進制位都有與之對應(yīng)的偏移量(從 0 開始),通過這些偏移量可以對位圖中指定的一個或多個二進制位進行操作。
實際上,位圖并不是 Redis 提供的一種新的數(shù)據(jù)類型,它是字符串類型的擴展。所以位圖的命令可以直接使用在字符串類型的鍵上,位圖命令操作的鍵也可以被字符串類型命令操作。
比如,現(xiàn)有一個字符串鍵 foo:
redis set foo bar
1 個字節(jié)由 8 個二進制位組成,所以 foo 鍵的二進制形式就是:
SETBIT
通過 SETBIT 命令,可以為位圖指定偏移量上的二進制位設(shè)置值,offset 必須大于等于 0,value 只能是 0 或 1。此命令的時間復(fù)雜度是 O(1)。
SETBIT key offset value
SETBIT 命令在對二進制位進行設(shè)置之后,將返回二進制位被設(shè)置之前的舊值作為結(jié)果。
假設(shè)現(xiàn)在想把 bar 變?yōu)?aar,只需如下兩步操作:
redis setbit foo 6 0
(integer) 1
redis setbit foo 7 1
(integer) 0
redis get foo aar
當(dāng)執(zhí)行 SETBIT 命令嘗試對一個位圖進行設(shè)置的時候,如果位圖不存在,或者位圖當(dāng)前的大小無法滿足,Redis 將對被設(shè)置的位圖進行擴展,并將所有未被設(shè)置的二進制位的值初始化為 0。比如:
redis setbit far 10 1
由于 far 并不存在,所以 Redis 會將 0~9 的二進制位設(shè)置為 0,因為 Redis 對位圖的擴展操作是以字節(jié)為單位進行的,所以實際上 far 一共有 16 個二進制位,并不是 10 個,且 11~15 的二進制位也是 0。
基于這種情況,當(dāng)指定的二進制位偏移量過大時,Redis 需要一次性分配完所有內(nèi)存,這可能會造成 Redis 服務(wù)器阻塞。比如存儲用戶的性別,1 代表男性,0 代表女性,使用 ID 作為二進制偏移量,如果 ID 從 10000000001 開始的,就需要將用戶 ID 減去 10000000000 再進行存儲,否則會造成內(nèi)存浪費。
GETBIT
使用 GETBIT 命令可以獲取位圖指定偏移量上的二進制位的值。此命令的時間復(fù)雜度是 O(1)。
GETBIT key offset
如果輸入的偏移量超過了位圖目前擁有的最大偏移量,將返回 0 作為結(jié)果。
BITCOUNT
通過 BITCOUNT 命令可以統(tǒng)計位圖中值為 1 的二進制位數(shù)量。此命令的時間復(fù)雜度是 O(n)。
BITCOUNT key [start end]
在默認情況下,BITCOUNT 命令對位圖包含的所有字節(jié)中的二進制位進行統(tǒng)計,也可以通過可選的 start 參數(shù)和 end 參數(shù),讓 BITCOUNT 只對指定字節(jié)范圍內(nèi)的二進制位進行統(tǒng)計(不是二進制偏移量)。比如,希望統(tǒng)計 ar 兩個字節(jié)中值為 1 的二進制數(shù)量:
redis bitcount foo 1 2
(integer) 7
start 和 end 參數(shù)也支持使用負數(shù)索引,下方的用法與上方的等效:
redis bitcount foo -2 -1
(integer) 7
BITPOS
通過執(zhí)行 BITPOS 命令,在位圖中查找第一個被設(shè)置為指定值的二進制位,并返回這個二進制位的偏移量。
BITPOS key value [start end]
BITPOS 也接受可選的 start 參數(shù)和 end 參數(shù),讓 BITPOS 命令只在指定字節(jié)范圍內(nèi)的二進制位中進行查找。
redis get foo aar redis bitpos foo 1
(integer) 1
redis bitpos foo 0
(integer) 0
redis bitpos foo 0 1 2
(integer) 8
redis bitpos foo 1 1 2
(integer) 9
redis bitpos foo 1 -1 -1
(integer) 17
針對邊界的處理:
當(dāng)嘗試對一個不存在的位圖或者一個所有位都被設(shè)置成了 0 的位圖中查找值為 1 的二進制位時,BITPOS 命令將返回 -1 作為結(jié)果。
如果在一個所有位都被設(shè)置成 1 的位圖中查找值為 0 的二進制位,那么 BITPOS 命令將返回位圖最大偏移量加上 1 作為結(jié)果
BITOP
通過 BITOP 命令,對一個或多個位圖執(zhí)行指定的二進制位運算,并將運算結(jié)果存儲到指定的鍵中。
BITOP operation destkey key [key …]
operation 參數(shù)的值可以是 AND、OR、XOR、NOT 中的任意一個,這 4 個值分別對應(yīng)邏輯并、邏輯或、邏輯異或和邏輯非 4 種運算,其中 AND、OR、XOR 這 3 種運算允許用戶使用任意數(shù)量的位圖作為輸入,而 NOT 運算只允許使用一個位圖作為輸入。BITOP 命令在將計算結(jié)果存儲到指定鍵中之后,會返回被存儲位圖的字節(jié)長度。
當(dāng) BITOP 命令在對兩個長度不同的位圖執(zhí)行運算時,會將長度較短的那個位圖中不存在的二進制位的值看作 0。
redis set foo1 bar
redis set foo2 aar
redis bitop or res foo1 foo2
(integer) 3
redis get res car
注意:BITOP 可能是一個緩慢的命令,它的時間復(fù)雜度是 O(N),在處理長字符串時應(yīng)注意一下效率問題。
應(yīng)用場景用戶行為記錄器
用用戶 ID 作為偏移量,若用戶做了某種行為則通過 SETBIT 將二進制位設(shè)置為 1,通過 GETBIT 判斷用戶是否做了某種行為,通過 BITCOUNT 可以知道有多少用戶執(zhí)行了行為。
用戶上線統(tǒng)計
可以使用 SETBIT 和 BITCOUNT 來實現(xiàn),以用戶 ID 作為 key,假設(shè)今天是上線統(tǒng)計功能開放的第一天,ID 為 1 的用戶上線后就通過 SETBIT 1 0 1。當(dāng)要計算此用戶的總共以來的上線次數(shù)時,使用 BITCOUNT 命令就可以得出的結(jié)果。
使用這種方式存儲數(shù)據(jù),即使 10 年后,1 個用戶就只占用幾百字節(jié)的內(nèi)存,它的處理速度依然很快。如果 bitmap 數(shù)據(jù)比較大,建議將 bitmap 拆分成多個小的 bitmap 分別進行處理。
到此,相信大家對“Redis 中的 bitmap 是什么”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!