今天,我和大家分享下redis在運維數(shù)據(jù)分析中的去重統(tǒng)計方式。為了避免混淆,本文中對于redis的數(shù)據(jù)結構做如下約定:
SET:saddkey member
ZSET:zaddkeyscoremember
HYPERLOGLOG:pfaddkey element
STRING:setbitkey offset value
名詞約定:
維度:比如版本、操作系統(tǒng)類型、操作系統(tǒng)版本、運營商、設備型號、網(wǎng)絡類型等
復合維度:由兩個或多個維度交錯產(chǎn)生的維度,比如某個版本下的某個設備型號。
去重統(tǒng)計在數(shù)據(jù)化運維的指標計算環(huán)節(jié),并不是一個陌生的字眼,甚至可以說,在大部分的數(shù)據(jù)指標的中間計算過程中,最終會分為以下幾種數(shù)據(jù)集:
最大,最小,穩(wěn)定性,疊加,去重統(tǒng)計。
這5種指標前面4種在實時處理框架或者大部分nosql中使用相對較小的開銷即可完成計算,基礎指標計算的大部分計算瓶頸還是落在io上面,而導致io瓶頸的問題源自于數(shù)據(jù)維度的劃分與聚合,特別是對于去重統(tǒng)計類型的數(shù)據(jù),如果有一種需要實時顯示的去重指標,維度的切分對于io上的開銷簡直是一種災難。
例如,假定我們需要獲取手機終端中某個應用版本中的某個設備型號或者某個系統(tǒng)的活躍設備數(shù)。那么,目前市場中的設備型號有幾百種,各種系統(tǒng)版本x系統(tǒng)類型也有很多,對指標的去重統(tǒng)計來說每多一個維度,需要的內(nèi)存開銷就要多上一倍,2個維度交叉產(chǎn)生的復合維度可能多達上百個,3個維度的交叉產(chǎn)生的復合維度可能數(shù)以千計。
因此,對于實時顯示的去重統(tǒng)計類型指標,最好的處理方式是在設計時盡量規(guī)避這種指標。如果實在無法規(guī)避,我們需要做的犧牲一部分插入時的性能或者空間上的性能換來該部分指標在讀取時不是o(n)的。
下面簡單介紹幾種在開發(fā)中基于redis研究出來的幾種數(shù)據(jù)去重方式:
1.于set的去重統(tǒng)計
這種結構的數(shù)據(jù)應該是最好理解的統(tǒng)計方式,也是常規(guī)的統(tǒng)計方式之一,直接把要去重的部分作為member插入一個set中,需要統(tǒng)計的時候直接使用scard統(tǒng)計該數(shù)據(jù)集的基數(shù),對于時間等維度信息,可以放在key中,然后拿取的時候通過拼接維度字段的形式拿取。
圖1 set的去重統(tǒng)計
優(yōu)點:使用簡單,統(tǒng)計精確。
缺點:無法達成實時統(tǒng)計的功能,要一分鐘統(tǒng)計一次的話需要使用expire命令設置一個很短的回收時間,單一維度時占用空間過大,信息聚合成本過大,有幾個維度就需要幾倍的內(nèi)存空間,3個以上復合維度時基本不需要考慮此方案。
適用場景:需要統(tǒng)計的去重內(nèi)容的基數(shù)非常小的情況下可以考慮,在優(yōu)云mobile中,對于用戶基數(shù)較小的影響設備數(shù)的計算采用了此種方式。
2.基于zset的去重統(tǒng)計
傳統(tǒng)的基于跳表/B樹的統(tǒng)計方式,key為維度信息,score為時間,member為設備id等原子信息,通過zcount可以拿取所有的成員數(shù)量。
優(yōu)點:插入和統(tǒng)計都是o(log(N))的,可以精確統(tǒng)計從現(xiàn)在開始到某個時間點的用戶,可以保留原子數(shù)據(jù)。
圖2 zset的去重統(tǒng)計
缺點:只能自定義時間域上的左區(qū)間,對于右區(qū)間只能定義為現(xiàn)在時間,否則會出現(xiàn)統(tǒng)計值比實際值偏小的情況(因為同一個設備如果出現(xiàn)兩次,則會移除舊的那條),單一維度時占用空間過大,有幾個維度就需要幾倍的內(nèi)存空間,3個以上復合維度時基本不需要考慮此方案。
適用場景:對于查看從現(xiàn)在開始1分鐘 5分鐘 10分鐘等各種時間跨度的用戶基數(shù)時可以考慮,在優(yōu)云mobile中,采用了這種方案來統(tǒng)計活躍設備數(shù),早期開發(fā)時我們將各種時間維度和各種復合維度全部放在了redis中,結果發(fā)現(xiàn)內(nèi)存開銷過大,現(xiàn)在的版本我們只存放了最近2分鐘的一些簡單維度的數(shù)據(jù)。
3.基于bitset的去重統(tǒng)計
將終端用戶id映射為一個bitset上的一個bit,利用現(xiàn)代處理器的特性進行快速計算。
優(yōu)點:統(tǒng)計結果精確,對于不同維度可以使用and或者or進行聚合,數(shù)據(jù)具有原子性,通過較少的操作即可做到跨維度的計算。
圖3 bitset的去重統(tǒng)計
缺點:不適用于分鐘級別的統(tǒng)計,并且用戶id的映射較為麻煩。如果使用hash的方式進行映射,將會不可避免的產(chǎn)生hash碰撞,如果使用用戶id進行映射,那么必然需要維護一份用戶id映射表,這份映射表放在內(nèi)存中會占用大量空間,放在磁盤中則會導致整個系統(tǒng)的處理速率降低。
備注:java中的bitset在一個byte字節(jié)上是由低位到高位進行存儲,redis中則是由高位到低位進行存儲。
適用場景:適用于需要儲存原子數(shù)據(jù)并進行較大時間跨度或者自由拼接時間跨度聚合的場景。
4.基于hyperloglog的去重統(tǒng)計
hyperloglog是一種基于概率的統(tǒng)計方式,在redis的2.8.9版本后出現(xiàn)的新數(shù)據(jù)結構
詳細的內(nèi)容可以查看這幾篇文章:
http://blog.codinglabs.org/tag.html#基數(shù)估計
優(yōu)點:每個hyperloglog只需要12K的空間,并且誤算率只有0.81%,不同的紀錄之間可以進行聚合,也就是可以通過聚合統(tǒng)計出任意時間范圍的去重結果,統(tǒng)計單個hyperloglog時時間復雜度為o(1)。
缺點:對于統(tǒng)計結果要求較為精確的場合并不是非常適用
適用場景:在對誤算率要求不高的情況下,同bitset。
5.基于布隆過濾器的去重統(tǒng)計
布隆過濾器是一種改良的bit映射方案,通過使用多種不同的hash種子,可以做到在較低誤判率以及較高的空間利用率的情況下進行統(tǒng)計,redis中并沒有布隆過濾器這個數(shù)據(jù)結構,不過可以通過lua腳本的方式實現(xiàn)一個布隆過濾器,詳細源碼可見
https://github.com/erikdubbelboer/redis-lua-scaling-bloom-filter1
圖4 布隆過濾器的去重統(tǒng)計
優(yōu)點:對于200萬用戶不超過萬分之一誤算率的統(tǒng)計,只需要8M左右redis內(nèi)存即可完成統(tǒng)計,萬分之一的誤算率是在插入的不同設備數(shù)達200萬次時才擁有的誤算率,在這之前的誤算率是從0開始線性增長的,在大多數(shù)情況下這個誤算率應該是可以容忍的。
缺點:布隆過濾器的統(tǒng)計結果無法聚合
適用場景:對于一些需要實時顯示的內(nèi)容并且維度較少的內(nèi)容,可以采用此數(shù)據(jù)結構,在優(yōu)云mobile中,總覽頁面的活躍設備數(shù)采用了此方案來實時顯示今日活躍設備數(shù)。
核心關注:拓步ERP系統(tǒng)平臺是覆蓋了眾多的業(yè)務領域、行業(yè)應用,蘊涵了豐富的ERP管理思想,集成了ERP軟件業(yè)務管理理念,功能涉及供應鏈、成本、制造、CRM、HR等眾多業(yè)務領域的管理,全面涵蓋了企業(yè)關注ERP管理系統(tǒng)的核心領域,是眾多中小企業(yè)信息化建設首選的ERP管理軟件信賴品牌。
轉載請注明出處:拓步ERP資訊網(wǎng)http://www.ezxoed.cn/
本文標題:漫談redis在運維數(shù)據(jù)分析中的去重統(tǒng)計方式
本文網(wǎng)址:http://www.ezxoed.cn/html/solutions/14019319372.html