最近被大佬問到一個問題,hbase查詢數據在最壞的場景下須要進行幾回rpc,當時就懵了..下面主要對client端代碼進行分析。閱讀文章和看源碼更配~html
1. 從zookeeper中獲取meta信息,並經過meta信息找到須要查找的table的startkey所在的region信息java
2. 和該region所在的regionserver進行rpc交互獲取result數據庫
3. region server查詢memstore(memstore是是一個按key排序的樹形結構的緩衝區),若是有該rowkey,則直接返回,若沒有進入步驟4數組
4. 查詢blockcache,若是有該rowkey,則直接返回,若沒有進入步驟5緩存
5. 查詢storefile,無論有沒有都直接返回優化
hbase讀數據除了直接操做hfile以外有3個入口,get(),batch()和scan(),get()相對而言就比較簡單,找到對應的regionserver而後發rpc便可,batch()採用單rpc多action的策略流程和get()相似,下面主要對scan涉及的核心接口進行分析。核心接口有如下幾個日誌
Connection:負責和zk創建鏈接server
Table:負責維護相關對象htm
ResultScanner:負責給使用者遍歷紓解對象
Caller:負責調用Callable
Callable:客戶端和hbase交互的主要接口
默認的鏈接器是HConnectionImplementation,能夠經過配置`hbase.client.connection.impl`修改。核心思路是基於zk的watcher,保持長鏈接,而後獲取hbase元數據
table經過Connection.getTable()實例化,默認的實現是HTable。這個類比較簡單,只是維護了針對hbase一張表所用到的對象。主要關注遍歷的方法,經過HTable.getScanner()實例化一個新的ResultScanner,使用者經過ResultScanner迭代器遍歷獲取result數據。
client提供了4種scanner,參考HTable.getScanner(),1. ClientScanner,讀取result的流程須要3次rpc,openScanner,next和closeScanner;2. 針對小量數據優化的ClientSmallScanner,和ClientScanner的區別在於,將openScanner,next和closeScanner合併到一個rpc執行,官方建議拉取的數據在64KB以內能夠考慮用SmallScanner的方式;另外兩個是基於reversed配置,也就是倒序遍歷region,須要交換startkey和endkey的位置。ClientScanner是咱們最經常使用的Scanner,也是默認的Scanner,下面對其進行分析
ClientScanne對應的Callable是ScannerCallable,也是最典型的Callable,下面對其核心方法進行分析
prepare()方法
核心call()方法
hbase-client的scan操做整體上能夠當作是兩層迭代器,面向使用者的Scanner以及面向region server的Callable。Callable負責從regionserver中獲取result,主要解決,Scanner負責整合result提供給使用者。這樣作的思路很明顯,數據大小是確定會大於內存的,經過迭代器接口,可讓使用者處理完以前的result再拉取其餘result,從而起到分頁的效果,這操做對使用者是透明的。若是須要詳細的scan日誌,能夠經過配置`hbase.client.log.scanner.activity`來打開開關,默認是false。
對於scan操做而言,拿ClientScanner來講,一次「完整rpc」過程包含3次rpc,open,result和close。若是失敗了,region不可用或者在split,那麼client會重試新的一次「完整rpc」,那麼就是6次rpc。其餘操做會少一點,例如SmallClientScanner一次「完整rpc」只須要1次rpc,它把open,close集成到了一塊兒。hbase在client仍是花了很多心思的。
HBase-1.3.1代碼