Redis 點陣圖基礎到統計活躍使用者

曲鎮發表於2020-03-08

前言

大家有沒有想過如何統計活躍使用者數量?如果是自己做,那該怎麼做?

這裡思考一分鐘,後面我將分享一下如何使用 redis 中的點陣圖來統計活躍使用者數。

正文

什麼是點陣圖 ?

點陣圖(bitmap) 是二進位制的 byte 陣列,也可以簡單理解成是一個普通字串。它將二進位制資料儲存在 byte 陣列中以達到儲存資料的作用。

Redis 點陣圖基礎到統計活躍使用者

圖 1.1

如何使用點陣圖 ?

理清概念

在解釋什麼是點陣圖的時候說過,點陣圖可以理解成是一個普通字串,那麼我們為什麼要用點陣圖而不是字串呢 ?

下面是在 redis 中儲存字串的一個示意圖

Redis 點陣圖基礎到統計活躍使用者

圖 2.1

如圖,儲存字串是將字串二進位制陣列的形式儲存在 redis 中,點陣圖可以直接對 二進位制的陣列操作,點陣圖的優勢在於可以用 0 和 1來儲存布林值,這大大降低了我們的儲存空間消耗。由於這個特性,我們用點陣圖來記錄簽到資訊,記錄活躍使用者等,可以達到節省空間的能力(後面會有介紹)。

那我們如何對二進位制的陣列進行操作呢?

基本存取

setbit | getbit

上文說的二進位制陣列我們可以對它做新增、查詢及修改的功能

如何進行新增和查詢呢?

setbit [keyName] [offset] [value]
複製程式碼

offset:偏移量,指的是陣列的下標; value: 資料, 只能是 0 和 1。

這條命令既可以新增資料也可以修改資料。

如何進行查詢呢 ?

getbit [keyName] [offset]
複製程式碼

offset:偏移量,指的是陣列的下標。這裡,除了設定 value 為 1 的 offset, 查詢其他的都返回 0

補充:上面說了點陣圖可以理解成字串,那麼它們之間可以互相操作嗎?

Redis 點陣圖基礎到統計活躍使用者

圖 2.2

請對照上圖,我們一起完成下面的探究:
  1. 以字串儲存,可以通過 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
    複製程式碼

    結論:可以的

  2. 以字串儲存,可以通過 settbit 修改值嗎?

    我們可以試著將 offset 7 對應的 value 改成 1, 如果成功了,h 字元應該變成 i

    > setbit str 7 1
    (integer) 0
    
    > get str
    "ii"
    複製程式碼

    結論:可以

  3. 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 個應用場景:

  1. 統計活躍使用者的數量
  2. 獲取第一次簽到和第一次未簽到的時間

我在這裡稍微介紹一下思路,然後附上一個 統計活躍使用者的數量 可供參考

統計活躍使用者的數量

  1. 將點陣圖的 keyName 設定成需要統計的 行為和時間範圍 [ation:date], 如:login:2020-3
  2. 將使用者對應到點陣圖中的 offset, 如 id 對應二進位制陣列的下標,idint
  3. 簽到成功使用 setbit 將對應的offset 設定成 1
  4. 使用 bitcount 統計某個行為和時間範圍的活躍人數,如 bitcount login:2020-3

Demo: DailyActiveUsers

獲取第一次簽到和第一次未簽到的時間

  1. 將點陣圖的 keyName 設定成需要統計的 行為和時間範圍和物件 [ation: date:person], 如:login:2020-3:Tom
  2. 將日期對應到點陣圖中的 offset, 如 1號對應二進位制陣列的下標 0, 2 號為 1
  3. 簽到成功使用 setbit 將對應的offset 設定成 1
  4. 使用 bitpos 統計某個行為和時間範圍和物件的簽到情況,如 bitpos login:2020-3:Tom 1

總結

  1. 點陣圖和字串沒有本質上的區別,只是操作方式不同
  2. 使用點陣圖儲存布林資料可以大大節省空間
  3. 存取命令 setbit/getbit
  4. 統計查詢 bitcount / bitpos

最後

上述內容對大家有所幫助的話,請幫我 點個贊?,分享不易,感謝支援!

如果本文有任何錯誤,感謝各位批評指教 !

相關文章