分布式快取Redis之bitmap setbit

2021-08-14 09:33:29 字數 3355 閱讀 2940

本學習教程所有示例**見github:

1)setbit

redis 127.0.0.1:6379> setbit key_name offset value //該命令用於對 key 所儲存的字串值,設定或清除指定偏移量上的位(bit)。時間複雜度o(1)
在redis中,儲存的字串都是以二進位制的形式存在的。比如:設定乙個key-value,鍵的名字叫「andy」 ,值為字元』a』,『a』 的ascii碼是97。轉換為二進位制是:01100001。offset的學名叫做「偏移」 ,二進位制中的每一位就是offset值,比如在這裡offset 0 等於 『0』 ,offset 1等於』1』 ,offset2等於』1』,offset 6 等於』1』 ,沒錯,offset是從左往右計數的,也就是從高位往低位。

那如何通過setbit命令將 andy中的 『a』 變成 『b』 呢?即將 01100001 變成 01100010(b的ascii碼是98),其實就是將』a』中的offset 6從0變成1,將offset 7從1變成0。

每次setbit完畢之後,有乙個(integer) 0或者(integer)1的返回值,這個是在你進行setbit 之前,該offset位的位元值。最後通過get andy得到的結果變成了 『b』 。

2)bitcount

redis 127.0.0.1:6379> bitcount andy //該命令統計字串(位元組)被設定為1的bit數
經過setbit操作之後,andy代表的01100010(b的ascii碼是98),共有3個1。

這裡需要注意一點的是!!!!!!!!

bitcount 統計的是1的個數, bitcount test 0 -1 就是所有的, bitcount 0 0 那麼就應該是第乙個位元組中1的數量的,注意是位元組第乙個位元組也就是 0 1 2 3 4 5 6 7 這八個位置上。見下面的測試樣例,setbit單位是bit,bitcount是以byte為間隔統計的

3)getbit

redis 127.0.0.1:6379> getbit andy offset  	//返回key對應的string在offset處的bit值
4)bitop

redis 127.0.0.1:6379> bitop operation destkey key [key...]  //對乙個或多個儲存二進位制位的字串 key 進行位元操作,並將結果儲存到 destkey 上
bitop 命令支援and 、 or 、 not 、 xor這四種操作中的任意一種引數:

除了 not 操作之外,其他操作都可以接受乙個或多個 key 作為輸入,執行結果將始終保持到destkey裡面。

當 bitop 處理不同長度的字串時,較短的那個字串所缺少的部分會被看作 0。返回值是儲存到 destkey 的字串的長度(以位元組byte為單位),和輸入 key 中最長的字串長度相等。

setbit 可以理解是乙個位陣列,至於這個陣列有多大,redis中bit對映被限制在512mb之內,所以最大是2^32。也就是在這樣乙個位陣列上存0或者是1 ,可以結合bloomfilter的應用場景理解位陣列的用法,將字串使用一種合適雜湊函式對映到不同的bit位上(2^32足夠的大,可以滿足需求)

使用 bitmap 實現使用者上線次數統計、統計活躍使用者

比如說,通過將乙個使用者的id對應value上的一位,通過對活躍使用者對應的位進行置位,就能夠用乙個value記錄所有活躍使用者的資訊。如圖bitmap有9個位被置為1,表示這9個位上對應的使用者是今天的活躍使用者。其中第15位表示uid為15的使用者,第一位表示uid為0的使用者。(如果你的uid不是從1開始的,比如從100000開始,實際上你也可以相應的用uid減去初始值來表示其位數,比如1000000使用者對應到bitmap的第一位)

redis.setbit(play:yyyy-mm-dd, user_id, 1)
這樣一次記錄的複雜度是o(1),在redis中速度非常快。而我們通過每天換用乙個不同的key來將每天的活躍使用者狀態記錄分開存。比如我們通過對3天(周一週三周四)的活躍使用者記錄取and操作,就能得出這3天都活躍的使用者列表

通過上圖中的測試樣例可以發現:

節約空間,統計一億人每天的登入情況,用一億bit,約1200wbyte,約10m的字元就能表示(因為bitop命令的返回值是儲存到 time中的字串的長度(以位元組byte為單位),和輸入 key 中最長的字串長度相等。即1億除以8bit=1250萬byte);

計算方便。

如果你的 bitmap 資料非常大,那麼可以考慮使用以下兩種方法:

● 將乙個大的 bitmap 分散到不同的 key 中,作為小的 bitmap 來處理。使用 lua 指令碼可以很方便地完成這一工作。

● 使用 bitcount 的 start 和 end 引數,每次只對所需的部分位進行計算,將位的累積工作(accumulating)放到客戶端進行,並且對結果進行快取 (caching)。

如果活躍使用者在百萬級別,使用redis bitmap很划算。

如果活躍使用者很少,而使用者id都是10位以上的int。那就很浪費記憶體了,還不如使用set集合,然後求交集就可以了。

------至所有正在努力奮鬥的程式猿們!加油!!有碼走遍天下 無碼寸步難行

1024 - 夢想,永不止步!

愛程式設計 不愛bug

愛加班 不愛黑眼圈

固執 但不偏執

瘋狂 但不瘋癲

生活裡的菜鳥

工作中的大神

身懷寶藏,一心憧憬星辰大海

追求極致,目標始於高山之巔

一群懷揣好奇,夢想改變世界的孩子

一群追日逐浪,正在改變世界的極客

你們用最美的語言,詮釋著科技的力量

你們用極速的創新,引領著時代的變遷

——github:

Redis 分布式快取

1 官網 3 菜鳥教程 4 redis的集群教程 5 史上最全redis高可用技術解決方案大全 一 redis的特點?redis 本質上是乙個 key value 型別的記憶體資料庫,很像 memcached,整個 資料庫統統載入在記憶體當中進行操作,定期通過非同步操作把資料庫資料 flush 到硬...

分布式快取Redis之資源釋放

本學習教程所有示例 見github 比如下面一段 for int i 2000 i 3000 i 在上面的 中,當迴圈到600次的時候,就會報出拿不到連線的錯誤,而600恰好是配置中的連線個數 並且jedis連線不會在使用結束後進行自動釋放 因為報錯後,再次請求這個方法,連乙個連線都拿不到了 如果在...

分布式快取Redis之效能測試

本學習教程所有示例 見github redis 效能測試是通過同時執行多個命令實現的。redis 效能測試的基本命令如下 redis benchmark option option value 以下例項同時執行 10000 個請求來檢測效能 redis benchmark n 100000 ping...