0 概述
隨著業(yè)務(wù)的推進,對數(shù)據(jù)的實時性要求更高,比如需要知道一個業(yè)務(wù)上線帶來的實時流量缆娃,去衡量它上線之后的效果,實時的獲取預(yù)算消耗情況瑰排,實時的掌握應(yīng)用的響應(yīng)情況贯要,并且根據(jù)聚合結(jié)果再處理。
基于有一定實時流計算基礎(chǔ)的情況凶伙,下面著重介紹設(shè)計過程中應(yīng)該注意的地方郭毕。
1 設(shè)計方面
1.1 數(shù)據(jù)的傾斜它碎、不平均
在APP中函荣,統(tǒng)計一個活動區(qū)塊的實時流量,區(qū)塊可能被劃分為多塊扳肛,針對不同的用戶傻挂,個性化推薦不同的活動,每個活動有bizId
比較簡單的設(shè)計就是直接對bizId進行field grouping挖息,然后統(tǒng)計bizId的PV金拒,UV等。但是有些活動會被推薦給多個用戶,有些活動只會推薦少數(shù)用戶绪抛,導(dǎo)致每個邏輯統(tǒng)計bolt處理的數(shù)據(jù)不夠平均
上圖中资铡,bizdId為1的流量較大,對應(yīng)的Task處理壓力大幢码,會有消息堆積的情況笤休。
比較好的解決方法是:
- 我們先進行一次散列(直接用Storm的shuffle grouping ),在第一層 bolt 中症副,保證每個task處理數(shù)據(jù)量大致相等店雅,但是這樣數(shù)據(jù)會分散到每個task。
然后分發(fā)繼續(xù)可以使用field grouping贞铣,對之前已經(jīng)聚合過一次的結(jié)果闹啦,在第二層bolt中,進行匯總辕坝。
- 也有第二種解決方法窍奋,就是設(shè)計比較好的fileding grouping字段,保證每個字段的數(shù)據(jù)量大致相等(也就是自己思考如何散列)酱畅,需要具體情況费变,具體分析
1.2 計算結(jié)果的聚合/更新方式
計算結(jié)果的聚合方式有三種
- 一種是全量式,按照時間間隔進行聚合圣贸,比如我統(tǒng)計1分鐘的PV挚歧,那我在內(nèi)存中進行聚合計算,一分鐘之后再進行存儲吁峻,存在的問題是滑负,如果這個Bolt掛了,被重啟用含,那可能就丟了之前已經(jīng)聚合的一部分數(shù)據(jù)
- 第二種覆蓋式矮慕,我提高寫入頻率,比如雖然是統(tǒng)計1分鐘的數(shù)據(jù)啄骇,我每10秒就寫入一次痴鳄,寫入過程判斷是否存在這分鐘數(shù)據(jù),如果存在就update缸夹,否則直接存儲痪寻。
- 第三種中心式,利用Redis進行存儲虽惭,因為我們基本上value都是一個int類型的值橡类,所以對redis操作的,KV加起來的字節(jié)數(shù)很小芽唇,在W級別的QPS下顾画,響應(yīng)時間avg基本可以在5MS下(同機房),因此我們的統(tǒng)計可以直接對redis操作,但是這樣的做法是比較土豪的方式研侣,消耗redis資源比較厲害谱邪,但是只做短時間的存儲,另外起一個bolt庶诡,對存儲的key進行記錄虾标,周期性的,對已經(jīng)存儲過的key可以進行l(wèi)oad form redis 再 save to db 灌砖,進行持久化璧函。
1.3 延時數(shù)據(jù)的統(tǒng)計
在大多數(shù)的實時流計算中,我們監(jiān)聽的是kafka的消息基显,進行消息處理蘸吓。
一般情況下,kafka的性能很高撩幽,partion的設(shè)計使得可以承擔(dān)更高的QPS库继,所以消息的到達幾乎是沒有延時的。
但是我們的topology 是無狀態(tài)的窜醉,在我們進行重啟宪萄,部署的時候,我們可以從offset開始消費榨惰,但是消息已經(jīng)不是實時的拜英,而是之前一段時間的,可以理解為消息到達的延時
比較好的處理方法是,所有的日志都需要帶上時間戳琅催,消息處理的時候居凶,應(yīng)該以日志自帶時間戳為準,而不是以消息處理的時間為準藤抡。
1.4 超大數(shù)據(jù)的去重統(tǒng)計
在統(tǒng)計UV的時候侠碧,我們是基于用戶的ID統(tǒng)計的,如果用戶量少缠黍,那么可以直接用set或者map之類的弄兜,但是對于一些百萬級別的用戶,特別是統(tǒng)計不同維度的訪問用戶瓷式,就會成倍增加數(shù)據(jù)量替饿。
這里有兩種方法:
布隆過濾器,布隆過濾器是由K個散列函數(shù)和一個二進制向量組成蒿往,當(dāng)一個元素加入時盛垦,K個散列函數(shù)將元素映射到二進制向量的的K個點湿弦,并且置為1瓤漏。檢索時就看這些點是不是都是1,這個方法是可行的,但是誤差比較隨機
HyperLogLog蔬充,這是用來做基數(shù)統(tǒng)計的算法蝶俱,RedisAPI自帶,因此在我們的項目中饥漫,我們實際使用的就是這種方法榨呆,當(dāng)然它也是一種誤差范圍內(nèi)的算法。一般誤差是在0.81%下
引用官方文檔的說明
The HyperLogLog data structure can be used in order to count uniqueelements in a set using just a small constant amount of memory, specifically 12k bytes for every HyperLogLog (plus a few bytes for the key itself).
The returned cardinality of the observed set is not exact, but approximated with a standard error of 0.81%.
2 監(jiān)控方面
2.1 kafka消息的堆積
kafka消息直接做法是利用現(xiàn)成的監(jiān)控工具查看庸队,可以看到消息到達量和消費量
2.2 StormUI
用storm自帶的Storm-UI就可以比較清楚的知道自己拓撲的情況积蜻,注意它也是采樣的,不是精確的彻消。
2.3.1每個bolt的性能
UI中點入自己的topology
鼠標放到對應(yīng)英文上面就可以知道每個指標的含義
比如Execute執(zhí)行時間竿拆,處理時間等。
2.3.3bolt的消息堆積情況
在Topology Visualization中點開宾尚,可以看到每個bolt的球球丙笋,其中顏色的深淺說明了消息的堆積情況。
其中從上往下說明堆積越來越嚴重