使用Redis bitmap進行活躍用戶統計

本文來自Spool的開發者博客,描述了Spool利用Redisbitmaps相關的操做,進行網站活躍用戶統計工做。java

Redis支持對String類型的value進行基於二進制位的置位操做。經過將一個用戶的id對應value上的一位,經過對活躍用戶對應的位進行置位,就可以用一個value記錄全部活躍用戶的信息。以下圖所未,下圖中的bitmap有9個位被置爲1,表示這9個位上對應的用戶是今天的活躍用戶。其中第15位表示uid爲15的用戶,第一位表示uid爲0的用戶。(若是你的uid不是從1開始的,好比從100000開始,實際上你也能夠相應的用uid減去初始值來表示其位數,好比1000000用戶對應到bitmap的第一位)
redis

具體的代碼相似下面這樣:sql

redis.setbit(play:yyyy-mm-dd, user_id, 1)

這樣一次記錄的複雜度是O(1),在Redis中速度很是快。
而咱們經過天天換用一個不一樣的key來將天天的活躍用戶狀態記錄分開存。而且能夠經過一些與或運算計算出N天活躍用戶,和鏈接N天活躍用戶這樣的統計數據。
以下圖,第一行表示星期一的活躍用戶狀況,第二行表示週二的,以此類推。爲樣咱們經過對N天的活躍用戶記錄取並集操做,就能得出在N天內活躍過的用戶列表。
nosql

下面表格表示對應一天,一週,一個月統計時所花費的時間。網站

Period Time (ms)
Daily 50.2
Weekly 392.0
Monthly 1624.8

下面是具體的java代碼片段:ui

1.算出一天的活躍用戶數量spa

import redis.clients.jedis.Jedis;
import java.util.BitSet;
...
  Jedis redis = new Jedis("localhost");
...
  public int uniqueCount(String action, String date) {
    String key = action + ":" + date;
    BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
    return users.cardinality();
  }

2.計算某幾個內活躍用戶的數量(某一天活躍就算,因此是取並集)code

import redis.clients.jedis.Jedis;
import java.util.BitSet;
...
  Jedis redis = new Jedis("localhost");
...
  public int uniqueCount(String action, String... dates) {
    BitSet all = new BitSet();
    for (String date : dates) {
      String key = action + ":" + date;
      BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
      all.or(users);
    }
    return all.cardinality();
  }

具體的用法還不少,好比你還能夠對獨特終端的用戶單獨記一個bitmap,這樣就能夠統計不一樣終端用戶的活躍狀況。有的同窗會說用set也能實現一樣的效果。但使用set在內存使用量上是會大不少的。blog

相關文章
相關標籤/搜索