本文主要是從HBase應用程序設計與開發的角度,總結幾種常用的性能優化方法。有關HBase系統配置級別的優化,可參考:淘寶Ken Wu同學的博客。
下面是本文總結的第四部分內容:數據計算相關的優化方法。
4. 數據計算
4.1 服務端計算
Coprocessor運行於HBase RegionServer服務端,各個Regions保持對與其相關的coprocessor實現類的引用,coprocessor類可以通過RegionServer上classpath中的本地jar或HDFS的classloader進行加載。
目前,已提供有幾種coprocessor:
- Coprocessor:提供對於region管理的鈎子,例如region的open/close/split/flush/compact等;
- RegionObserver:提供用於從客戶端監控表相關操作的鈎子,例如表的get/put/scan/delete等;
- Endpoint:提供可以在region上執行任意函數的命令觸發器。一個使用例子是RegionServer端的列聚合,這里有代碼示例。
以上只是有關coprocessor的一些基本介紹,本人沒有對其實際使用的經驗,對它的可用性和性能數據不得而知。感興趣的同學可以嘗試一下,歡迎討論。
4.2 寫端計算
4.2.1 計數
HBase本身可以看作是一個可以水平擴展的Key-Value存儲系統,但是其本身的計算能力有限(Coprocessor可以提供一定的服務端計算),因此,使用HBase時,往往需要從寫端或者讀端進行計算,然后將最終的計算結果返回給調用者。舉兩個簡單的例子:
- PV計算:通過在HBase寫端內存中,累加計數,維護PV值的更新,同時為了做到持久化,定期(如1秒)將PV計算結果同步到HBase中,這樣查詢端最多會有1秒鍾的延遲,能看到秒級延遲的PV結果。
- 分鍾PV計算:與上面提到的PV計算方法相結合,每分鍾將當前的累計PV值,按照rowkey + minute作為新的rowkey寫入HBase中,然后在查詢端通過scan得到當天各個分鍾以前的累計PV值,然后順次將前后兩分鍾的累計PV值相減,就得到了當前一分鍾內的PV值,從而最終也就得到當天各個分鍾內的PV值。
4.2.2 去重
對於UV的計算,就是個去重計算的例子。分兩種情況:
- 如果內存可以容納,那么可以在Hash表中維護所有已經存在的UV標識,每當新來一個標識時,通過快速查找Hash確定是否是一個新的UV,若是則UV值加1,否則UV值不變。另外,為了做到持久化或提供給查詢接口使用,可以定期(如1秒)將UV計算結果同步到HBase中。
- 如果內存不能容納,可以考慮采用Bloom Filter來實現,從而盡可能的減少內存的占用情況。除了UV的計算外,判斷URL是否存在也是個典型的應用場景。
4.3 讀端計算
如果對於響應時間要求比較苛刻的情況(如單次http請求要在毫秒級時間內返回),個人覺得讀端不宜做過多復雜的計算邏輯,盡量做到讀端功能單一化:即從HBase RegionServer讀到數據(scan或get方式)后,按照數據格式進行簡單的拼接,直接返回給前端使用。當然,如果對於響應時間要求一般,或者業務特點需要,也可以在讀端進行一些計算邏輯。
5. 總結
作為一個Key-Value存儲系統,HBase並不是萬能的,它有自己獨特的地方。因此,基於它來做應用時,我們往往需要從多方面進行優化改進(表設計、讀表操作、寫表操作、數據計算等),有時甚至還需要從系統級對HBase進行配置調優,更甚至可以對HBase本身進行優化。這屬於不同的層次范疇。
總之,概括來講,對系統進行優化時,首先定位到影響你的程序運行性能的瓶頸之處,然后有的放矢進行針對行的優化。如果優化后滿足你的期望,那么就可以停止優化;否則繼續尋找新的瓶頸之處,開始新的優化,直到滿足性能要求。
以上就是從項目開發中總結的一點經驗,如有不對之處,歡迎大家不吝賜教。