前言
大家有沒有想過如何統計活躍使用者數量?如果是自己做,那該怎麼做?
這裡思考一分鐘,後面我將分享一下如何使用 redis 中的點陣圖來統計活躍使用者數。
正文
什麼是點陣圖 ?
點陣圖(bitmap) 是二進位制的 byte 陣列,也可以簡單理解成是一個普通字串。它將二進位制資料儲存在 byte 陣列中以達到儲存資料的作用。
圖 1.1
如何使用點陣圖 ?
理清概念
在解釋什麼是點陣圖的時候說過,點陣圖可以理解成是一個普通字串,那麼我們為什麼要用點陣圖而不是字串呢 ?
下面是在 redis 中儲存字串的一個示意圖
圖 2.1
如圖,儲存字串是將字串二進位制陣列的形式儲存在 redis 中,點陣圖可以直接對 二進位制的陣列操作,點陣圖的優勢在於可以用 0 和 1來儲存布林值,這大大降低了我們的儲存空間消耗。由於這個特性,我們用點陣圖來記錄簽到資訊,記錄活躍使用者等,可以達到節省空間的能力(後面會有介紹)。
那我們如何對二進位制的陣列進行操作呢?
基本存取
setbit | getbit
上文說的二進位制陣列我們可以對它做新增、查詢及修改的功能
如何進行新增和查詢呢?
setbit [keyName] [offset] [value]
複製程式碼
offset:偏移量,指的是陣列的下標; value: 資料, 只能是 0 和 1。
這條命令既可以新增資料也可以修改資料。
如何進行查詢呢 ?
getbit [keyName] [offset]
複製程式碼
offset:偏移量,指的是陣列的下標。這裡,除了設定 value 為 1 的 offset, 查詢其他的都返回 0
補充:上面說了點陣圖可以理解成字串,那麼它們之間可以互相操作嗎?
圖 2.2
請對照上圖,我們一起完成下面的探究:-
以字串儲存,可以通過
getbit
命令獲取到值嗎?我們可以結合查詢和圖片所示的 offset 及所對應的值來驗證
> set str hi OK > getbit str 0 (integer) 0 > getbit str 4 (integer) 1 > getbit str 7 (integer) 0 > getbit str 15 (integer) 1 複製程式碼
結論:可以的
-
以字串儲存,可以通過
settbit
修改值嗎?我們可以試著將 offset 7 對應的 value 改成 1, 如果成功了,h 字元應該變成 i
> setbit str 7 1 (integer) 0 > get str "ii" 複製程式碼
結論:可以
-
用
setbit
儲存字串的二進位制資料,可以通過get
獲取字串嗎?我們將 字元 h 的二進位制存入點陣圖,看可以能通過 get 獲取
> setbit bitmap 0 0 (integer) 0 > setbit bitmap 1 1 (integer) 0 > setbit bitmap 2 1 (integer) 0 > setbit bitmap 3 0 (integer) 0 > setbit bitmap 4 1 (integer) 0 > setbit bitmap 5 0 (integer) 0 > setbit bitmap 6 0 (integer) 0 > setbit bitmap 7 0 (integer) 0 > get bitmap "h" 複製程式碼
結論:可以
上面介紹了點陣圖的基本概念和使用,通過一系列的探究希望能幫助大家更好的理解點陣圖
那麼,如何將點陣圖應用的專案中呢?
統計和查詢
bitcount | bitpos
bitcount
是用來查詢 1 出現的次數,既可以對點陣圖使用也可以對字串使用,用法如下:
bitcount [keyName] [startWith] [endWith]
複製程式碼
注意:這裡的 startWith 和 endWith 不是二進位制陣列的下標(offset)
這裡的 startWith 和 endWith 可以理解成是字串的下標,一個字串對應 8 位二進位制資料;它們相當於是擷取字串,如 s= "hi"
, s[0:0] = "h"
, 它所對應的二進位制陣列的下標是 0,7,以此類推。
其實這裡不好解釋,先來帶程式碼,可以結合著上面的 圖 2.2 看一下,大家後面可以在領悟一下
> set str hi
> bitcount str 0 0
(integer) 4
> bitcount str 0 1
(integer) 8
> bitcount str
(integer) 8
複製程式碼
注意:startWith 和 endWith 不設定的時候預設全部範圍
應用場景:統計活躍使用者的數量
bitpos
用來查詢指定範圍內出現的第一個 0 或 1,用法如下:
bitpos [keyName] [bit] [start] [end]
複製程式碼
bit: 要找的 0 或者 1, start 和 end 同上面的 startWith 和 endWith
應用場景:獲取第一次簽到和第一次未簽到的時間
應用場景
上面大致說了 2 個應用場景:
- 統計活躍使用者的數量
- 獲取第一次簽到和第一次未簽到的時間
我在這裡稍微介紹一下思路,然後附上一個 統計活躍使用者的數量 可供參考
統計活躍使用者的數量
- 將點陣圖的 keyName 設定成需要統計的 行為和時間範圍 [ation:date], 如:
login:2020-3
- 將使用者對應到點陣圖中的
offset
, 如id
對應二進位制陣列的下標,id
為int
- 簽到成功使用
setbit
將對應的offset
設定成 1 - 使用
bitcount
統計某個行為和時間範圍的活躍人數,如bitcount login:2020-3
Demo: DailyActiveUsers
獲取第一次簽到和第一次未簽到的時間
- 將點陣圖的 keyName 設定成需要統計的 行為和時間範圍和物件 [ation: date:person], 如:
login:2020-3:Tom
- 將日期對應到點陣圖中的
offset
, 如 1號對應二進位制陣列的下標 0, 2 號為 1 - 簽到成功使用
setbit
將對應的offset
設定成 1 - 使用
bitpos
統計某個行為和時間範圍和物件的簽到情況,如bitpos login:2020-3:Tom 1
總結
- 點陣圖和字串沒有本質上的區別,只是操作方式不同
- 使用點陣圖儲存布林資料可以大大節省空間
- 存取命令 setbit/getbit
- 統計查詢 bitcount / bitpos
最後
上述內容對大家有所幫助的話,請幫我 點個贊?,分享不易,感謝支援!
如果本文有任何錯誤,感謝各位批評指教 !