一、需求背景 首先,我們來看一下需求:網站統計用戶登錄的次數,具體如下: 網站有1億個用戶,有經常登錄的,也有不經常登錄的 如何來記錄用戶的登錄信息 如何查詢活躍用戶:比如:一周內,登錄3次的 二、使用傳統的關係型資料庫 我們使用傳統的關係型資料庫(比如:Oracle)來存儲這樣的數據,如下圖所示。 ...
一、需求背景
首先,我們來看一下需求:網站統計用戶登錄的次數,具體如下:
- 網站有1億個用戶,有經常登錄的,也有不經常登錄的
- 如何來記錄用戶的登錄信息
- 如何查詢活躍用戶:比如:一周內,登錄3次的
二、使用傳統的關係型資料庫
我們使用傳統的關係型資料庫(比如:Oracle)來存儲這樣的數據,如下圖所示。
每周產生7億條數據,對於任何一個關係型資料庫來說,都是非常不好維護的,對性能也會有很大的影響。
三、使用Redis的setbit操作
Redis支持對String類型的value進行基於二進位位的置位操作。通過將一個用戶的id對應value上的一位,通過對活躍用戶對應的位進行置位,就能夠用一個value記錄所有活躍用戶的信息。如下圖所未,下圖中的bitmap有9個位被置為1,表示這9個位上對應的用戶是今天的活躍用戶。其中第15位表示uid為15的用戶,第一位表示uid為0的用戶。(如果你的uid不是從1開始的,比如從100000開始,實際上你也可以相應的用uid減去初始值來表示其位數,比如1000000用戶對應到bitmap的第一位)
具體的代碼類似下麵這樣:redis.setbit(key, user_id, 1)
這樣一次記錄的複雜度是O(1),在Redis中速度非常快。
下麵代碼是在Redis CLI中執行的Demo演示,比如:用戶ID為100的用戶在星期一登錄了網站,我們就通過setbit操作,把星期一對應的100位的值置為1,
127.0.0.1:6379> setbit monday 100 1 (integer) 0而我們通過每天換用一個不同的key來將每天的活躍用戶狀態記錄分開存。並且可以通過一些與或運算計算出N天活躍用戶,和連接N天活躍用戶這樣的統計數據。
如下圖,第一行表示星期一的活躍用戶情況,第二行表示周二的,以此類推。為樣我們通過對N天的活躍用戶記錄取並集操作,就能得出在N天內活躍過的用戶列表。