HBase客戶端查詢存在的問題
- Scan
用Get/Scan查詢數據, - Filter
用Filter查詢特定數據
以上情況只適合幾千行數據以及不是很多的列的“小數據”。
當表擴展為億萬行及百萬列時,在通過網絡傳遞移動大量的數據導致網絡擁堵,且客戶端需要足夠多內存來處理這么大量數據的計算操作,另外,客戶端代碼也會變的大而復雜。
解決方案
移動計算比移動數據更划算
Coprocessor將運算移動到數據所處的節點。
什么是Coprocessor?
簡單來說,Coprocessor是一個框架,這個框架可以讓你很容易地在Region Server運行你的業務邏輯代碼。
Coprocessor類比
- Triggers and Stored Procedure
- Observer Coprocessor –> RDBMS 中的觸發器
- EndPoint Coprocessor –> RDBMS中的存儲過程
- MapReduce
MapReduce 和 Coprocessor有一樣的操作原則,計算向數據靠攏。
- AOP
類似面向切面編程,Coprocessor就像應用Advice,在傳遞請求到最終的目的地之前,通過攔截一個請求后運行相同的代碼。
Coprocessor分類
Observer Coprocessor
在一個特定的事件發生前或發生后觸發。
- 在事件發生前觸發的Coprocessor需要重寫以pre作為前綴的方法,比如prePut。
- 在事件發生后觸發的Coprocessor使用方法以post作為前綴,比如postPut。
Endpoint
是一個遠程rpc調用,類似於webservice形式調用,但他不適用xml,而是使用的序列化框架是protobuf(序列化后數據更小).
區別:Observer像是個觸發器,到某個條件Region就去執行用戶代碼,用戶從主觀來說是無法控制的;EndPoint就是遠程調用,用戶可以在客戶端遠程調用執行自己的代碼。
Observer Coprocessor使用場景與實現
Observer Coprocessor的使用場景如下:
安全性:在執行Get或Put操作前,通過preGet或prePut方法檢查是否允許該操作;
引用完整性約束:HBase並不直接支持關系型數據庫中的引用完整性約束概念,即通常所說的外鍵。但是我們可以使用Coprocessor增強這種約束。比如根據業務需要,我們每次寫入user表的同時也要向user_daily_attendance表中插入一條相應的記錄,此時我們可以實現一個Coprocessor,在prePut方法中添加相應的代碼實現這種業務需求。
二級索引:可以使用Coprocessor來維持一個二級索引。這里暫不展開,有時間會單獨說明。
Observer在Hbase中主要分為四類,均繼承Coprocessor接口:
- RegionObserver 針對於Region的觀察者(Region打開、關閉、刷新、合並等工作)
- RegionServerObserver 針對RegionServer的觀察者(Region合並、分裂、日志回滾等)
- MasterObserver 針對Master的觀察者(表創建、刪除、Region移動、拆分等工作)
- WALObserver 針對WAL的觀察者(日志寫)
EndPoint使用場景與實現
Endpoint允許定義自己的動態RPC協議,用於客戶端與region servers通訊。Coprocessor 與region server在相同的進程空間中,因此您可以在region端定義自己的方法(endpoint),將計算放到region端,減少網絡開銷,常用於提升hbase的功能,如:count,sum等。
工作過程如下圖所示過程:
- 不管是通過配置還是表描述加載了EndPoint協處理器
- 在Client執行CoprocessorExec()調用對應的RPC方法
- 在對應的每個region中都會執行該方法后返回結果
- EndPoint實現
- 創建一個“.proto”文件定義服務
- 執行protoc命令,通過“.proto”文件生成Java代碼
- 編寫一個Coprocessor類,實現Coprocessor和CoprocessorService兩個接口,並實現接口中定義的方法:
- 加載Coprocessor
- 編寫客戶端代碼調用Coprocessor
裝載Coprocessor
裝載Coprocessor分為靜態裝載和動態裝載。
靜態裝載Coprocessor
- 靜態裝載過程:
-
- hbase-site.xml中創建記錄
-
- 將代碼放到HBase的類路徑下。一個簡單的方法是將封裝好的jar(包括代碼和依賴)放到HBase安裝路徑下的/lib目錄中。
-
- 重啟HBase。
- 靜態卸載的步驟如下:
- 移除在hbase-site.xml中的配置。
- 重啟HBase。
- 這一步是可選的,將上傳到HBase類路徑下的jar包移除。
動態裝載Coprocessor
動態裝載Coprocessor的一個優勢就是不需要重啟HBase。不過動態裝載的Coprocessor只是針對某個表有效。因此,動態裝載的Coprocessor又被稱為表級Coprocessor。
此外,動態裝載Coprocessor是對表的一次schema級別的調整,因此在動態裝載Coprocessor時,目標表需要離線。
動態裝載Coprocessor有兩種方式:通過HBase Shell和通過Java API。
- 通過HBase Shell動態裝載
- 使用Java API動態裝載和卸載
http://www.zhyea.com/2017/04/13/using-hbase-coprocessor.html#Observer-Coprocessors
達摩克利斯之劍
Coprocessor是HBase的高級功能,本來是只為HBase系統開發人員准備的。因為Coprocessor的代碼直接在RegionServer上運行,並直接接觸數據,這樣就帶來了數據破壞的風險,比如“中間人攻擊(Man-in-the-MiddleAttack,簡稱“MITM攻擊”,見百度詞條)”以及其他類型的惡意入侵。目前還沒有任何機制來屏蔽Coprocessor導致的數據破壞。此外,因為沒有資源隔離,一個即使不是惡意設計的但表現不佳的Coprocessor也會嚴重影響集群的性能和穩定性。
其他公司實踐
二級索引設計
Phoenix的Salting功能非常有效,但對延遲影響較大,因此若延遲要求較高,那么Salting則並不合適,所以這里在主表與索引表中不使用Salting功能,而是采用reverse將主鍵列散列。索引中使用Function Index和Function Index減少查詢延遲。