基於 hbase 做 storm 實時計算指標儲存
hbase 實時指標儲存是我入職樂視雲後對原有的實時系統改造的
hbase 儲存設計
storm 結果如何儲存到 hbase
hbase 寫入效能優化
與傳統方案 (redis/mysql) 對比
樂視雲內部用 storm 做 cdn,點播,直播流量的計算,同時還有慢速比,卡頓比等統計指標。相應的指標會由指標名稱,業務型別,客戶,地域,isp 等多個維度組成。指標計算乙個比較大的問題是 key 的集合很大。
舉個例子,假設我們有客戶 10w,計算指標假設 100 個,5 個 isp,30 個地域,這樣就有億級以上的 key 了,我們還要統計分鐘級別,小時級別,天級別,月級別。所以寫入量和儲存量都不小。
如果採用 redis/memcached 寫入速度是沒有問題的,畢竟完全的記憶體操作。但是 key 集合太大,其實壓力也蠻大的,我去的時候因為加了指標,結果導致 memcache 被寫爆了,所以緊急做了擴容。
首先是 redis 查起來的太麻煩。客戶端為了某個查詢,需要彙總成千上萬個 key。。。業務方表示很蛋疼,我們也表示很蛋疼
其次,記憶體是有限的,只能存當天的。以前的資料需要轉存。
第三,你還是繞不過持久化儲存,於是引入 mysql,現在是每天一張表。那 redis 匯入到 mysql 本身就麻煩。所以工作量多了,查詢也麻煩,查乙個月半年的資料就**了。
鑑於以上原因,我們就想著有沒有更合適的方案。
我們首先就想到了 hbase,因為 hbase 還是具有蠻強悍的寫入性功能以及優秀的可擴充套件性。而事實上經過調研,我們發現 hbase 還是非常適合指標查詢的,可以有效的通過列來減少 key 的數量。
我們現在上圖:
這裡,我們一行可以追蹤某個指標一天的情況。如果加再加個維度,無非增加一條記錄。而如果是 redis,可能就多了一倍,也就是 2880 個 key 了。
我們知道 hbase 是可以多列族,多 column,schemaless 的。所以這裡,我們建了乙個列族,在該列族上,直接建了 1440 個 column。column 的數目和時間粒度有關。如果是一分鐘粒度,會有 1440 個,如果是五分鐘粒度的會有 288 個,如果是小時粒度的,會有 24 個。不同的粒度,我們會建不同的表。
寫入的時候,我們可以定位到 rowkey,以及對應的 column,這裡一般不會存在併發寫。當然 hbase 的 increment 已經解決了併發問題,但是會造成一定的效能影響。
查詢的時候,可根據天的區間查出一條相應的記錄。我們是直接把記錄都取出來,column 只是乙個 int/long 型別,所以 1440 個 column 資料也不算大。
storm 計算這一塊,還有乙個比較有意思的地方。假設 a 指標是五分鐘粒度的,也就是說我們會儲存 a 指標每個五分鐘的值。但是在實際做儲存的時候,他並不是五分鐘結束後就往 hbase 裡儲存,而是每隔(幾秒/或者一定條數後)就 increment 到 hbase 中,然後清除重新計數。
這裡其實我要強調的是,到 hbase 並不是覆蓋某個 rowkey 特定的 cloumn 值,而是在它原有的基礎上,做加法。這樣做可以防止時間週期比較長的指標,其累計值不會因為有拓撲當掉了而丟失資料(其實還是會丟的,但可能損失的計數比較少而已)。
丟資料比如你 kill-9 了。
大家可以想象一下,如果我計算乙個五分鐘的指標,到第三分鐘掛掉了,此時累計值是 1000,接著拓撲重啟了,五分鐘還沒完,剩下的兩分鐘它會接著累計,此時是 500。如果是覆蓋寫,就會得到不正確的結果,實際上整個完整的計數是 1500。
防止拓撲當掉並不是這樣設計的主要原因,還有一點是計算延時了,比如某個資料片段因為某個原因,延時了十分鐘才到 storm 實時計算集群,這個時候新得到的值還可以加回去,如果是覆蓋,資料就錯誤了。
所以 hbase 儲存這塊就變成做加法操作而不僅僅是簡單的更新了。目前 hbase 新增了計數的功能 (incrment),但是我發現跨行,沒有批量更新的的介面。
而 hbase 的 client 也是非常的奇特,比如 htablepool 竟然是物件池而不是鏈結池,多個 htable 物件是共享乙個 connection 鏈結的。當然,這裡 htable 的 connection 會比較複雜,因為要連 zookeeper 還有各個 region。
又沒有批量介面,乙個 client 只能有乙個 connection 鏈結,所以導致客戶端的寫入量死活上不去。16 臺 32g,24 核的伺服器,我做了預分割槽 (60個左右),用了四十個程序,300 個左右的執行緒去寫,也就只能寫到 60000/s 而已。
但實際併發應該是只有 40 左右的。300 個執行緒並沒有起到太多作用。
還有就是,hbase 的 incrementcolumnvalue 的效能確實不高。至少和批量 put 差距很大。
但在我們的測試中,還是比較平穩的,整個寫入狀態。抖動不大。
這裡要強調一點,hbase 看場景,在我們這個場景下是預分割槽是非常重要的。否則一開始都集中在一台機器的乙個 regin 上寫,估計很快寫的程序就都堵住了。上線就會掛。
所以我事先收集了幾天的 key,然後預先根據 key 的分布做了分割槽。我測試過,在我們的集群上,到了 60 個分割槽就是乙個瓶頸,再加分割槽已經不能提公升寫入量。
寫入我們也做了些優化,因為寫的執行緒和 storm 是混用的(其實就是 storm 在寫)。我們不能堵住了 storm。
當使用者提交了n條記錄進行更新操作,我會做如下操作:
將n條分成10份,每份n/10條。
每個jvm例項會構建乙個擁有10個執行緒的執行緒池。
執行緒池中的每個執行緒都會維護乙個connection(通過threadlocal完成)。
執行緒會對自己的這n/10條資料順序進行incrementcolumnvalue。
做這個優化的原因是我上面提到的,htable 的連線池是共享 connnection 的。我們這裡是為了讓每個執行緒都有乙個 connection。具體分成多少份(我這裡採用的是 10),是需要根據 cpu 來考量的。我們的伺服器 cpu 並不是很多。值不是越大越好。如果太大,比如我起了 40 個虛擬機器。每個虛擬機器 10 個執行緒,那麼會有 400 個到 zookeeper 和 hbase 的連線。值設定的過大,會對 zookeeper 有一定的壓力。
這種方案我測試的結果是:
吞吐量上去了。在 1500w 左右的測試資料中,原有的方式大概平均只有 3w/s 左右的寫入量。 通過新的方式,大概可以提高到 5.4w/s,只要 4 分鐘左右就能完成 1500w 條資料的寫入。
峰值略微提公升了一些。之前大約 6.1w/s,現在可以達到 6.6w/s。
因為我用同一集群上的 spark 模擬的提交,所以可能會對 hbase 的寫入有一點影響,如果想要繼續提公升寫入效能,只能重寫 hbase 這塊客戶端的**。
我們總結下上面的內容:
redis/mysql 儲存方案存在的一些缺點。
hbase 表結構設計,充分李永樂 hbase 自身的特點,有效的減少key的數量,提高查詢效率。
storm 寫入方案,用以保證出現資料延時或者 storm 拓撲當掉後不會導致資料不可用。
我們再看看整個儲存體系完整的拓撲圖。
第五個圓圈是為了在實時計算出錯時,通過 spark/mr 進行資料恢復。
第二個圓圈和第四個圓圈是為了做維度複製,比如我計算了五分鐘的值,這些值其實可以自動疊加到對應的小時和天上。我們稱為**程式
第三個圓圈就是對外吐出資料了,由我們的統一查詢引擎對外提供支援查詢支援了。
我們對查詢做乙個推演。如果我要給使用者繪製流量的乙個月曲線圖。曲線的最小粒度是小時,小時的值是取 12 個五分鐘裡最高的值,我們看看需要取多少條記錄完成這個查詢。
我們需要取 31 條五分鐘的記錄,每條記錄有 288 個點,對這 288 個點分成 24 份(具體就是把分鐘去掉 groupby 一下),求出每份裡的最大值(每組 sortby 一下),這樣就得到了 24 個值。
我取過兩天的,整個 http 響應時間可以控制 50ms 左右(本機測試)。
上面的整體架構中,**程式是為了緩解實時寫入 hbase 的壓力,同時我們還利用 mr/spark 做為恢復機制,如果實時計算產生問題,我們可以在小時內完成恢復操作,比如日誌的收集程式、分揀程式、以及格式化程式。格式化程式處理完之後是 kafka,storm 對接的是 kafka 和 hbase。
上面就是今天分享的內容了。
基於HBase做Storm 實時計算指標儲存
基於hbase做storm 實時計算指標儲存 舉個例子,假設我們有客戶 10w,計算指標假設 100 個,5 個 isp,30 個地域,這樣就有億級以上的 key 了,我們還要統計分鐘級別,小時級別,天級別,月級別。所以寫入量和儲存量都不小。如果採用 redis memcached 寫入速度是沒有問...
hbase基於solr的實時索引
實時查詢方案 hbase key value store solr web前端實時查詢展示 1.hbase 提供海量資料儲存 2.solr提供索引構建與查詢 3.key value store 提供自動化索引構建 從hbase到solr 使用流程 前提 cdh5.3.2solr集群搭建好,cdh5....
關於Storm實時往HBase存資料的效能優化
在開發中根據業務邏輯,需要儲存在storm中每個spout和bolt中產生的資料到hbase表中。在程式調優的過程中不斷調整和優化了幾種方案。這是首先考慮和測試的選擇,也是最先放棄的選擇,短時多次建立連線會造成資源的浪費和排隊,儲存的時間的過長也會影響topology流的穩定性和實時性。8.16補充...