HBase 二級索引實現方案
1. 概要設計
主要思路:
為每個DataTable建立一個與之對應的IndexTable,通過各種途徑,保證IndexTable Region與DataTable Region一一對應,並且儲存在同一個RegionServer上,儲存結構如圖所示。最終要實現的效果是,每個IndexTable Region是對應的DataTable Region的區域性索引,使用索引進行查詢時,將對每個IndexTable Region進行檢索,找出所有符合條件的DataTable RowKey,再根據DataTable RowKey到對應的DataTable Region中讀取相應DataTable Row。
2. 詳細設計
2.1. IndexTable的建立
IndexTable的建立主要出現在兩個時機,
一是建立新DataTable時,系統根據索引定義,自動建立對應的IndexTable;
二是對已存在的DataTable,使用者呼叫介面方法,動態建立索引。
IndexTable的建立過程如下:
第一步,:
獲取DataTable的所有RegionInfo,得到所有DataTable Region的StartKey。
第二步:
結合索引定義和DataTable Region的StartKey資訊,呼叫HBaseAdmin的createTable(final HTableDescriptor desc, byte [][] splitKeys)方法建立索引表。
通過以上兩步便建立了IndexTable Region和DataTable Region的以StartKey為依據的一一對應關係。
2.2. IndexTable RowKey的設計
IndexTable的RowKey由四部分組成,按順序依次是:DataTable Region StartKey、IndexName、IndexValue和DataTable RowKey,如圖所示。
DataTable Region StartKey。 將DataTable Region的StartKey作為IndexTable Region的RowKey的第一部分,主要基於兩個方面的考慮。
一是使得IndexTable Region和對應的DataTable Region擁有相同的StartKey,這樣便可將StartKey作為兩個Region的關聯依據;
二是當DataTable Region分裂時,可使用相同的SplitKey對IndexTable Region進行相應的分裂操作,並將新產生的DataTable Region和IndexTable Region建立關聯關係。
IndexName。
在一張DataTable的基礎上可以定義多個索引,如果為每個索引建立一個IndexTable,則在實際應用過程中,勢必會產生大量的IndexTable,當DataTable Region分裂時,還需要對與之關聯的所有IndexTable Region分別執行分裂操作,這將消耗大量的系統資源,並且不易維護。因此,我們考慮將一張DataTable的所有索引資料,存放到同一張IndexTable中,不同索引的資料以IndexName進行區分。
IndexValue。如果索引是單列索引,IndexValue就是DataTable Row的某個Column Value,如果索引是組合索引的話,則IndexValue就是DataTable Row的多個Column Value組合而成的。
DataTable RowKey。被用來定位DataTable Row,以獲取最終的資料。
2.3. IndexTable Region的分配控制
IndexTable Region的分配控制過程,即是保證IndexTable Region與DataTable Region的一一對應,並且被分配到同一個RegionServer的過程。
自定義LoadBalancer,重寫balanceCluster方法,主要增加對IndexTable Region的分配控制。以相同的StartKey作為IndexTable Region和DataTable Region的關聯依據,將IndexTable Region和與其對應的DataTable Region分配到同一個RegionServer。自定義LoadBalancer對IndexTable Region的分配控制過程如圖所示。
注意:
這裡只增加對IndexTable Region分配的控制,並不對DataTable Region的分配進行干預,DataTable Region由HBase按照指定的負載均衡策略進行分配,使得對現有HBase執行環境的影響降到最小。
2.4. IndexTable Region的分裂過程
本文將以一個示例講述IndexTable Region的分裂過程,假設當前有一個DataTable Region和對應的IndexTable Region,如圖所示,綠色表格為DataTable Region,紅色表格為IndexTable Region。
根據概要設計中的說明,假設SplitKey:03,經過一系列操作之後,原來的DataTable Region和IndexTable Region均分裂成兩個新的Region,並且依然儲存一一對應關係。最終效果如圖所示。
IndexTable Region具體分步驟說明如下:
第一步:
確定SplitKey後,遍歷IndexTable Region中所有的行,找出所有DataTable RowKey大於或等於SplitKey的Row,如圖所示。
第二步:
刪除第一步找到的所有DataTable RowKey大於或等於SplitKey的Row,並將RowKey的第一部分(DataTable Region StartKey)替換成SplitKey後,重新插入到IndexTable Region中,如圖所示。
第三步:
以SplitKey,同時對DataTable Region和IndexTable Region進行分裂操作,如圖所示。最終達到如圖所示的效果。
2.5. 資料的寫入過程
資料的寫入過程,主要通過Coprocessor代理完成,保證更新DataTable Region資料的同時更新IndexTable Region中的資料。具體步驟如圖所示。
2.6. 資料的讀取過程
與資料的寫入過程一樣,資料的讀取過程也是由Coprocessor代理完成。Coprocessor收到查詢請求後,首先判斷是否可以利用某個索引,提高本次查詢效率。如果有可用的索引,則先從IndexTable Region中查出所有符合條件的RowKey,再根據RowKey,從DataTable Region中查找出實際的資料返回給客戶端。具體步驟如圖所示。
注意:
描述的IndexTable Region分配機制,保證了IndexTable Region和對應的DataTable Region處於同一個RegionServer上,這樣便解決了在有大量符合查詢條件的Row的情況下,通過RowKey從DataTable Region中獲取實際資料的效率問題。
此外,考慮到從IndexTable中獲取的RowKey列表也是有序的,所以在實現時,並不直接呼叫HBase提供的Get介面,去獲取單個實際資料,而是在HFile Data Index的輔助下,通過遍歷HFile,獲取所有實際資料。
成都加米穀大資料科技有限公司是一家專注於大資料人才培養的機構。由來自阿里、華為、京東、星環等國內知名企業的多位技術大牛聯合創辦,技術底蘊豐厚,勤奮創新,精通主流前沿大資料及人工智慧相關技術。
以國家規劃大資料產業發展戰略為指引,以全國大資料技術和大資料分析人才的培養為使命,以提升就業能力、強化職業技術為目標。面向社會提供大資料、人工智慧等前沿技術的培訓業務。
