如何高效計算DAU
專案中一直有計算DAU這類的需求,業務開發者往往埋個點,其他是事情就交給資料團隊了。
如果自己要做一個這樣的計數器怎麼做呢?一個樸素的想法是透過hashmap實現,時間複雜度是O(1)。這個方法在計數物件較少的情況下還是不錯的,但是如果計數物件很多(比如計算獨立訪問IP),意味著hashmap的key非常多,記憶體消耗是非常大。
閱讀開源IM軟體GoBelieve程式碼,看到了下面一個函式
這個函式的目的是計算IM的日活使用者量,採用了redis一個命令“PFADD”。趕緊查一下幫助文件,看到下面一段執行記錄
這個方法用於計算日活DAU太合適不過。仔細檢視Redis文件,HyperLogLog結構下支援三個方法,PFADD,PFCOUNT,PFMERGE。透過這幾個方案,能夠很容易實現計數類的一些需求。
HyperLogLog是什麼?
HyperLogLog是一種基數估計演算法。在理解技術估計演算法之前,我們需要先知道基數計數法的概念(有沒有感覺讀書的時候似曾相識)。
基數計數(cardinality counting)通常用來統計一個集合中不重複的元素個數,例如統計某個網站的UV,或者使用者搜尋網站的關鍵詞數量。資料分析、網路監控及資料庫最佳化等領域都會涉及到基數計數的需求。 要實現基數計數,最簡單的做法是記錄集合中所有不重複的元素集合Su,當新來一個元素xi,若Su中不包含元素xi,則將xi加入Su,否則不加入,計數值就是Su的元素數量。這種做法存在兩個問題:
1、當統計的資料量變大時,相應的儲存記憶體也會線性增長(文章開始用hashmap技術的辦法就有這個問題)
2、當集合Su變大,判斷其是否包含新加入元素xi的成本變大
大資料量背景下,要實現基數計數,首先需要確定儲存統計資料的方案,以及如何根據儲存的資料計算基數值;另外還有一些場景下需要融合多個獨立統計的基數值,例如對一個網站分別統計了三天的UV,現在需要知道這三天的UV總量是多少,怎麼融合多個統計值。
除了hashmap,另一個容易被想到的辦法是點陣圖BitMap。點陣圖可以快速、準確地獲取一個給定輸入的基數。點陣圖的基本思想是使用雜湊函式把資料集對映到一個bit位,每個輸入元素與bit位是一一對應。這樣Hash將沒有產生碰撞衝突,並減少需要計算每個元素對映到1個bit的空間。點陣圖大大節省了空間,但是當統計很高的基數或非常大的不同的資料集,它的空間開銷依然較大,同時可能帶來稀疏點陣圖等問題。
技術估計演算法(HyperLogLog是其中一種)就是來解決海量資料技術難題的!基數估計演算法使用準確性換取空間。
為了說明這一點,這裡引用《Big Data Counting: How To Count A Billion Distinct Objects Using Only 1.5K》文章的實驗資料。
文章用三種不同的計算方法統計所有莎士比亞作品中不同單詞的數量。請注意,我們的輸入資料集增加了額外的資料以致比問題的參考基數更高。這三種技術是:Java HashSet、Linear Probabilistic Counter以及一個Hyper LogLog Counter。結果如下:
該表顯示,Hyper LogLog Counter統計這些單詞只用了512 bytes,而誤差在3%以內。相比之下,HashMap的計數準確度最高,但需要近10MB的空間,基數估計非常有用!在實際應用中,某些統計的準確性並不是很重要。在大多數網路規模和網路計算的情況下,用機率計數器會節省巨大的空間。
HyperLogLog的演算法原理可以搜尋《HyperLogLog the analysis of a near-optimal cardinality estimation algorithm》這篇文章。下邊截個演算法具體實現過程
演算法看不懂沒關係(很多做AI的人也不清楚反向傳播演算法),重要的是要知道怎麼正確使用Redis中實現的HyperLogLog演算法。
redis中實現的HyperLogLog,只需要12K記憶體,在標準誤差0.81%的前提下,能夠統計2^64個資料!
所以不要擔心統計資料太大,redis記憶體不夠用,放心使用就好。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31556438/viewspace-2218085/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [譯]計算機如何高效識別影像?計算機
- [譯]計算機如何高效識別影象?計算機
- 千萬級DAU系統該如何設計
- 北鯤雲超算平臺如何將雲端計算與高效能運算結合
- 直播預告 | 從0到千萬DAU,應用架構如何設計?應用架構
- HPC高效能運算知識: 異構平行計算
- 深度學習高效計算與處理器設計深度學習
- HPC高效能運算知識: 計算架構演進架構
- 雲端計算還有多久能夠替代高效能運算?
- 高效能運算-粒子狀態模擬計算最佳化
- Java日期時間API系列38-----一種高效的工作日計算計算方法JavaAPI
- 如何計算保證金
- 如何計算盈虧(PnL)
- kl散度如何計算
- 邊緣計算:晶片提供高效能人工智慧晶片人工智慧
- NVIDIA推出液冷GPU 助力實現可持續高效計算GPU
- 如何高效管理設計交付,提升設計團隊效率?
- 10 早期計算機如何程式設計計算機程式設計
- MySQL如何計算統計redo log大小MySql
- 【計算機內功心法】七:高併發高效能伺服器是如何實現的計算機伺服器
- “關機幣價”如何計算?
- 如何入門雲端計算?
- 子網掩碼如何計算
- MySQL | 05 如何設計高效能的索引?MySql索引
- 如何設計一個高效能 Elasticsearch mappingElasticsearchAPP
- 阿里面試:MySQL如何設計索引更高效?阿里面試MySql索引
- 高效能運算-openmp程式設計-深入理解(for-collapse)程式設計
- 高效能 Java 計算服務的效能調優實戰Java
- 厲害了量子計算機!瞧瞧它是如何“秒殺”其他計算機計算機
- 推廣訂單如何計算返利
- 量子計算將如何改變世界?
- 如何讓計算機理解語意?計算機
- 如何用python計算不定積分Python
- python如何計算數的階乘Python
- 如何高效引流
- 如何設計出高可用、高效能的介面
- 如何設計一個高效能的圖 Schema
- 參加UI設計培訓如何高效學習?UI