Hbase 讀取流程

Hbase 讀取復(fù)雜原因:

主要基于兩個(gè)方面的原因:

  • 一是因?yàn)镠Base一次范圍查詢可能會涉及多個(gè)Region、多塊緩存甚至多個(gè)數(shù)據(jù)存儲文件(HFile);
  • 二是因?yàn)镠Base中更新操作以及刪除操作的實(shí)現(xiàn)都很簡單。
    插入&刪除: 沒有更新原始數(shù)據(jù),而是通過時(shí)間戳屬性新增版本。
    刪除:只是插入deleted標(biāo)簽。在Major Compact的時(shí)候刪除真正數(shù)據(jù)。
    讀取過程需要根據(jù)版本進(jìn)行過濾,對已經(jīng)標(biāo)記刪除的數(shù)據(jù)也要進(jìn)行過濾。

讀流程步驟:

  • Client-Server讀取交互邏輯
  • Server端Scan框架體系
  • 過濾淘汰不符合查詢條件的HFile
  • 從HFile中讀取待查找Key。

1. Client-Server讀取交互邏輯

Client首先會從ZooKeeper中獲取元數(shù)據(jù)hbase:meta表所在的RegionServer,然后根據(jù)待讀寫rowkey發(fā)送請求到元數(shù)據(jù)所在RegionServer,獲取數(shù)據(jù)所在的目標(biāo)RegionServer和Region(并將這部分元數(shù)據(jù)信息緩存到本地),最后將請求進(jìn)行封裝發(fā)送到目標(biāo)RegionServer進(jìn)行處理。

  • hbase的讀取請求分為get和scan,而get實(shí)際是最簡單的一次scan。

  • client-server端將scan沒有使用一次rpc,原因:
    ?大量數(shù)據(jù)傳輸會導(dǎo)致集群網(wǎng)絡(luò)帶寬等系統(tǒng)資源短時(shí)間被大量占用,嚴(yán)重影響集群中其他業(yè)務(wù)。
    ?客戶端很可能因?yàn)閮?nèi)存無法緩存這些數(shù)據(jù)而導(dǎo)致客戶端OOM。


    image.png
  • 一次大的scan操作會拆分為多個(gè)RPC請求。每個(gè)RPC是一次next請求,分會規(guī)定數(shù)量的結(jié)果。每次next()操作,客戶端先檢查本地緩存,沒有就發(fā)一次RPC請求給服務(wù)器,然后緩存到本地。

  • 單次RPC caching大小默認(rèn)是Integer.MAX_VALUE。設(shè)置過大可能因?yàn)橐淮潍@取到的數(shù)據(jù)量太大導(dǎo)致服務(wù)器端/客戶端內(nèi)存OOM;設(shè)置太小會導(dǎo)致一次大scan進(jìn)行太多次RPC,網(wǎng)絡(luò)成本高。

  • 對于一張表列過大,可以通過setBatch方法設(shè)置一次RPC請求的數(shù)據(jù)列數(shù)量。

  • 客戶端還可以通過setMaxResultSize方法設(shè)置每次RPC請求返回的數(shù)據(jù)量大?。ú皇菙?shù)據(jù)條數(shù)),默認(rèn)是2G。

2 Server端Scan框架體系

  • 一次scan可能會同時(shí)掃描一張表的多個(gè)Region??蛻舳藭鶕?jù)hbase:meta元數(shù)據(jù)將掃描的起始區(qū)間[startKey, stopKey)進(jìn)行切分,切分成多個(gè)互相獨(dú)立的查詢子區(qū)間,每個(gè)子區(qū)間對應(yīng)一個(gè)Region。

  • HBase中每個(gè)Region都是一個(gè)獨(dú)立的存儲引擎,因此客戶端可以將每個(gè)子區(qū)間請求分別發(fā)送給對應(yīng)的Region進(jìn)行處理。下文會聚焦于單個(gè)Region處理scan請求的核心流程。

  • RegionServer接收到客戶端的get/scan請求之后做了兩件事情:首先構(gòu)建scanner iterator體系;然后執(zhí)行next函數(shù)獲取KeyValue,并對其進(jìn)行條件過濾。

image.png

image.png
  1. 構(gòu)建Scanner Iterator體系
    1)過濾淘汰部分不滿足查詢條件的Scanner。
    主要過濾策略有:TimeRange過濾、Rowkey Range過濾以及布隆過濾器


    image.png

    2)每個(gè)Scanner seek到startKey

  • 根據(jù)HFile索引樹定位目標(biāo)Block


    image.png
  • BlockCache中檢索目標(biāo)Block
    Block緩存到Block Cache之后會構(gòu)建一個(gè)Map,Map的Key是BlockKey,Value是Block在內(nèi)存中的地址。其中BlockKey由兩部分構(gòu)成——HFile名稱以及Block在HFile中的偏移量。BlockKey很顯然是全局唯一的。根據(jù)BlockKey可以獲取該Block在BlockCache中內(nèi)存位置,然后直接加載出該Block對象。如果在BlockCache中沒有找到待查Block,就需要在HDFS文件中查找。
  • HDFS文件中檢索目標(biāo)Block


    image.png

    根據(jù)文件索引提供的Block Offset以及Block DataSize這兩個(gè)元素可以在HDFS上讀取到對應(yīng)的Data Block內(nèi)容。

為什么HDFS的Block設(shè)計(jì)為128M,而HBase的Block設(shè)計(jì)為64K ?
1. HDFS Block 為128M,因?yàn)?主要存儲文件,Block太小,會導(dǎo)致Block元數(shù)據(jù)(Block所在DataNode位置、文件與Block之間的對應(yīng)關(guān)系等)龐大。因?yàn)镠DFS元數(shù)據(jù)都存儲在NameNode上,大量的元數(shù)據(jù)很容易讓NameNode成為整個(gè)集群的瓶頸。
2. HBase的緩存策略是緩存整個(gè)Block,如果Block設(shè)置太大會導(dǎo)致緩存很容易被耗盡,尤其對于很多隨機(jī)讀業(yè)務(wù),設(shè)置Block太大會讓緩存效率低下。

  • 從Block中讀取待查找KeyValue

3)KeyValueScanner合并構(gòu)建最小堆
最小堆管理Scanner可以保證取出來的KeyValue都是最小的,這樣依次不斷地pop就可以由小到大獲取目標(biāo)KeyValue集合,保證有序性。

執(zhí)行next函數(shù)獲取KeyValue并對其進(jìn)行條件過濾

1)檢查該KeyValue的KeyType是否是Deleted/DeletedColumn/DeleteFamily等
2)檢查該KeyValue的Timestamp是否在用戶設(shè)定的Timestamp Range范圍
3)檢查該KeyValue是否滿足用戶設(shè)置的各種filter過濾器
4)檢查該KeyValue是否滿足用戶查詢中設(shè)定的版本數(shù)

總結(jié): 讀取過程中,是先根據(jù)TimeRange,Rowkey Range,bloomfilter判斷數(shù)據(jù)是否在對應(yīng)文件,再將文件中的數(shù)據(jù)讀取出來,判斷是否刪除,是否符合用戶條件。

讀取過程總結(jié):

  1. 客戶端: 將scan 轉(zhuǎn)變?yōu)槎啻蝞ext請求。將請求轉(zhuǎn)變?yōu)榘l(fā)送對應(yīng)region(讀zk,讀meta找到對應(yīng)region)的請求
  2. 服務(wù)器端:過濾掉不符合查詢條件的hfile,讀取符合條件的hfile,構(gòu)建最小堆
    (1)過濾hfile方式:TimeRange,RowKey,bloomfiler
    (2) hfile索引樹定位目標(biāo)block
    (3)檢索block: blockcache中檢索、hdfs文件中檢索block
  3. 獲取keyvalue,next過濾:
    (1)keytype判斷是否刪除
    (2)timestamp判斷timerange
    (3) 判斷用戶filter
    (4) 判斷版本號
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容