redis實現統計使用者連續登陸天數

橘子味芬达水發表於2024-08-21

在很多app以及遊戲當中,經常會統計使用者連續登陸天數,使用mysql統計這份頻繁的資料有所欠缺以及結算等方面都是很大的負擔

存在的挑戰

  1. 資料如何儘可能用小的空間儲存
  2. 如何能快速獲取指定的資料

如果使用檔案儲存

會有如下問題:

  1. 檔案分割變得十分麻煩

  2. 資料檢索非常不方便

  3. 使用者關聯操作複雜

如果使用資料庫表

會有如下問題:

  1. 佔用空間增長速度快,表急劇增大
  2. 使用索引,易產生碎片,每次插入資料還要維護索引,影響效能
  3. 要用group ,sum等運算,計算較慢

使用redis點陣圖進行儲存(setbit/getbit)

使用者的簽到狀態無非兩種,我們按月來統計使用者簽到資訊,簽到記錄為1,未簽到則記錄為0.

把每一個bit位對應當月的每一天,形成了對映關係。用0和1標識業務狀態,這種思路就稱為點陣圖(BitMap)。我們用31個bit位(4位元組)即可表示我們一個月的簽到記錄,這樣就用極小的空間,實現了大量資料的表示。


Redis中是利用string型別資料結構實現BitMap,最大上限是512M,轉換為bit則是 2^32個bit位。BitMap的操作命令有:

SETBIT:向指定位置(offset)存入一個0或1
GETBIT :獲取指定位置(offset)的bit值
BITCOUNT :統計BitMap中值為1的bit位的數量
BITFIELD :操作(查詢、修改、自增)BitMap中bit陣列中的指定位置(offset)的值
BITFIELD_RO :獲取BitMap中bit陣列,並以十進位制形式返回
BITOP :將多個BitMap的結果做位運算(與 、或、異或)
BITPOS :查詢bit陣列中指定範圍內第一個0或1出現的位置

優點:

  1. 由於我的業務中只需要根據某個使用者id查詢是否是活躍使用者,不存在複雜的查詢條件,所以用redis很合適。
  2. redis中所有資料都是二進位制形式儲存的。redis支援一個setbit和getbit操作,它支援在某個key的value上直接對某個二進位制位操作,每個二進位制位都只有0和1兩種狀態,正好可以表示使用者是否活躍兩種狀態。
  3. 存取速度非常快

思路

  1. 記錄使用者登陸:每天按日期生成一個點陣圖, 使用者登陸後,把user_id位上的bit值置為1
  2. 把1周的點陣圖用 and 計算, 是否連續登陸用and計算,得到1即為連續登陸的使用者,簡單來說,能快速的拿到使用者是否登陸的0/1狀態,就能快速的計算出某段日期內登陸了幾天
  3. 如果每次執行redis比較繁瑣,可以簡單的生成追加檔案的方式,追加redis命令,例setbit到檔案中,隔一段時間統一利用pipe mode透過管道的方式直接快速存入redis

命令

redis 127.0.0.1:6379> setbit mon 3 1

(integer) 0

redis 127.0.0.1:6379> setbit mon 5 1

(integer) 0

redis 127.0.0.1:6379> setbit mon 7 1

(integer) 0

redis 127.0.0.1:6379> setbit thur 100000000 0

(integer) 0

redis 127.0.0.1:6379> setbit thur 3 1

(integer) 0

redis 127.0.0.1:6379> setbit thur 5 1

(integer) 0

redis 127.0.0.1:6379> setbit thur 8 1

(integer) 0

127.0.0.1:6379> getbit thur 8
(integer) 1

相關文章