如圖所示爲用戶留存分析功能前端
該柱狀圖展現的爲用戶留存百分比.redis
以按周展現爲例算法
U:活躍用戶數 x:第幾周 y:活躍佔比數據庫
需求整理:數組
對於這種數據後臺的功能,做爲服務端開發,咱們會盡可能要求數據庫將結果統計好,由咱們服務端直接取結果作展現.數據結構
可是因爲有隨機日期的對比,假設由數據組來進行統計,意味着須要對天天都作對比統計(統計結果數據量大,耗費性能),並不現實.性能
因此最終仍是決定由服務端來作實時統計.大數據
實時統計,主要考慮前端的響應速度.優化
採用bitmap按天緯度來存放用戶登陸數據..net
實現過程:
採用bitmap按用戶緯度存放登陸時間信息(哪幾天登陸)
記當天爲標準第0天
對每一個登陸用戶,將對每一個登陸用戶,將當前天數對應的位置爲1
當計算y(x(i))時
用戶 | 描述 | bitmap |
---|---|---|
a | 第-4,-3,-1,0天登陸 | [1,1,0,1,1] |
b | 第-3,-2,0天登陸 | [1,1,0,1] |
B(-3,0) | 第-3,0天登陸 | [1,0,0,1] |
B(0) | 第0天登陸 | [1] |
優勢 | 缺點 | |
---|---|---|
方案一 | 查詢快,只須要作一次and操做 | 空間佔用太大,天天都要以最大用戶量生成一條bitmap |
方案二 | 節省空間,空間佔用隨用戶量增加,每一個用戶的bitmap隨登錄狀況變化 | 查詢略慢,須要遍歷全部用戶作and操做 |
簡單歸納: 方案一費空間,方案二查詢慢
實際開發過程當中,因爲咱們採用redis進行存儲.
採用方案一的話內存過於浪費.而採用方案二,以個人macpro-i5配置只能負載20w/s的and操做,響應速度方面難以接受.
綜合上述方式一二都不能知足要求,只能看是否還有優化空間.
通過同事提醒,針對方式一採用一種空間壓縮算法,解決了方案一空間浪費的缺陷.
簡單歸納:
假設數據量爲不超過2^32.
將數據拆分爲高16位,低16位
對高位進行聚合(以高位作key,value爲有相同高位的全部低位數組)
根據低位的數據量(不一樣高位聚合出的低位數組長度不相同),使用不一樣的container(數據結構)存儲
len<4K ArrayContainer 直接存值
len>=4K BitmapContainer 使用bitmap存儲
4K的取值緣由:value的最大總數是爲2^16=65536. 假設以bitmap方式存儲須要65536bit=8kb,而直接存值的方式,一個值16,4K個總共須要2byte*4K=8kb.因此當value總量<4k時,使用直接存值的方式更節省空間
RunContainer 壓縮存儲
RunContainer中的Run指的是行程長度壓縮算法(Run Length Encoding),對連續數據有比較好的壓縮效果.對於數列11,12,13,14,15,21,22 它會壓縮爲11,4,21,1
空間壓縮主要體如今:
對數據的位操做速度有影響(3種container相互and.樂觀狀況兩個BitmapContainer作and切BitCount()>4096,則數據無影響)
綜上: 使用RoaringBitmap的優缺點
方案3能夠說是平衡了方案一二,是本次的最優選擇