日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HBase读链路分析

發(fā)布時間:2024/8/23 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HBase读链路分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

簡介:HBase的存儲引擎是基于LSM-Like樹實現(xiàn)的,更新操作不會直接去更新數(shù)據(jù),而是使用各種type字段(put,delete)來標記一個新的多版本數(shù)據(jù),采用定期compaction的形式來歸檔合并數(shù)據(jù)。這種數(shù)據(jù)結(jié)構(gòu)將寫操作變得非常簡單且高效,但是卻給讀造成了很大的困擾。讀取過程需要根據(jù)列族讀取不同HFile中的數(shù)據(jù);還需要根據(jù)版本進行過濾,同時對已經(jīng)標記刪除的數(shù)據(jù)也要進行過濾;硬盤中的數(shù)據(jù)與MemStore中的數(shù)據(jù)重合時,還需要執(zhí)行合并,最后在內(nèi)存中拼接成一行完整的數(shù)據(jù)再向上返回。 本文粗粒度地展示了HBase的讀取鏈路,歡迎一起探討交流~

正文之前

在講HBase的讀路徑時,我們先來看幾個簡單的類圖。

InternalScanner是一個Interface主要提供了兩個方法,next(List<Cell> result)方法——獲取下一行的數(shù)據(jù)。而next(List<Cell> result, ScannerContext scannerContext)提供功能相同,只不過允許傳入一個ScannerContext用以記錄當前scan任務(wù)的上下文,判斷是否可以提前結(jié)束、是否要去讀下一列、是否要去讀下一行等。并且發(fā)生在InternalScanner中的數(shù)據(jù)比較等操作,都是基于byte[](而不用先轉(zhuǎn)化為RowResults),更加接近于數(shù)據(jù)在物理上的存儲形式,可以獲得更高的性能。

KeyValueScanner也是一個接口,換成CellScanner可能更容易理解。對,它主要提供在一個“可讀取的對象上”,獲取cell的能力。這里使用“可讀取的對象”這個詞,主要是因為它可以是一個物理概念上的HFile,但也可以是邏輯意義上有迭代讀取能力的scanner。

最后一個關(guān)鍵的類就是KeyValueHeap,該類實現(xiàn)了KeyValueScanner與InternalScanner接口,具備了獲取cell及獲取行的能力。KeyValueHeap中還有一個關(guān)鍵的屬性,為heap,它是一個PriorityQueue<KeyValueScanner>對象,comparator = CellComparatorImp(即按照key的格式:rowkey:family:qualifier:timestamp)。即KeyValueHeap允許傳入多個KeyValueScanner,通過PriorityQueue的形式將這些scanner管理起來,向上提供獲取cell及獲取行數(shù)據(jù)的能力!

有了InternalScanner,KeyValueScanner和KeyValueHeap其實已經(jīng)可以做很多事情了。

我們知道,HBase的查詢抽象地來看的話,是表現(xiàn)為下面這個流程的:

即從不同的HFile中進行數(shù)據(jù)讀取,在內(nèi)存中進行一個MergeSort,拼接成一行數(shù)據(jù)向上返回。

你們看KeyValueScanner、InternalScanner是不是就像其負責中HFile的讀取Scanner,而KeyValueHeap負責的其實就是圖中的MergeSort的任務(wù)。KeyValueHeap控制著下層KeyValueScanner、InternalScanner的數(shù)據(jù)讀取,KeyValueScanner、InternalScanner是真正讀取數(shù)據(jù)的Scanner。

好,大體的流程思路已經(jīng)講清楚了。其實HBase的讀取流程遠比這復(fù)雜,涉及的對象也更多,但有了上面的基礎(chǔ)相信可以理解得很容易,接下來我們來仔細看看HBase的讀取流程。

正文

我們從RegionScanner出發(fā),仔細看看HBase的讀取流程。

上圖中的RegionScanner主要靠成員變量storeHeap,joinedHeap(KeyValueHeap)進行數(shù)據(jù)讀取迭代。而StoreScanner也不是一個單純的Scanner,而是扮演了跟RegionScanner類似的角色,它也擁有自己的heap,以此來進行數(shù)據(jù)的讀取。跟【正文之前】說的一樣,KeyValueHeap控制著下層KeyValueScanner、InternalScanner的數(shù)據(jù)讀取,KeyValueScanner、InternalScanner是真正讀取數(shù)據(jù)的Scanner。只不過RegionScanner中多嵌了一層StoreScanner(KeyValueHeap),變成了這樣的調(diào)用鏈路:KeyValueHeap(RegionScanner)->KeyValueHeap(StoreScanner)

->KeyValueScanner,InternalScanner(StoreFileScanner及SegmentScanner)。

為什么HBase要這樣封裝?

其實是為了抽象不同的功能。

簡單來說,

1)StoreScanner是為了聯(lián)合StoreFileScanner與SegmentScanner向上提供整行的數(shù)據(jù)迭代讀取功能。

2)而RegionScanner,一方面是對獲取的數(shù)據(jù)做了過濾功能,另一方面是為了將全部數(shù)據(jù)分為兩段獲取形式(storeHeap和joinedHeap),用以優(yōu)化性能。因為從storeHeap中獲取的數(shù)據(jù)如果會被過濾,那么就沒有必要再獲取joinedHeap中的數(shù)據(jù)了。

詳細內(nèi)容我們見下文。

HBase的讀取任務(wù)開始之前需要構(gòu)建初始的Scanner體系,涉及RegionScanner與StoreScanner的對象初始化,我們詳細來看:

1)RegionScanner對象的初始化:

1.建立RegionScanner對象,準備開始Scan任務(wù)涉及的所有Scanner的生成。

2.根據(jù)scan任務(wù)涉及的所有column family,在本region上分別會為其中的每個column family生成一個StoreScanner。如果開啟了on-demand column family loading,那么會根據(jù)傳入FilterList的isFamilyEssential方法進行判斷,如果isFamilyEssential,那么會將該StoreScanner放入storeHeap中,否則放入joinedHeap中

3.storeHeap和joinedHeap中存放StoreScanner的形式為PriorityQueue,優(yōu)先級為CellComparatorImp。

2)StoreScanner對象的初始化

接下來我們介紹RegionScanner對象的初始化中,我們一筆帶過的StoreScanner的生成過程:

1.根據(jù)scan.isReversed()控制StoreScanner中的Scanner的優(yōu)先級順序。

2.根據(jù)傳入的scan信息,生成matcher內(nèi)置對象,該對象在查詢過程中會對StoreScanner讀取的數(shù)據(jù)進行一個篩選。

3.根據(jù)scan信息startRow,stopRow在storeEngine中查詢出涉及的HStoreFile,對這些HStoreFile分別建立StoreFileScanner,組成scannerList,并且StoreFileComparators.SEQ_ID為優(yōu)先級(maxSequenceId升序,FileSize降序,BulkTime升序,PathName升序)。

4.對scannerList根據(jù)timestamp range, row key range, bloomFilter做一個過濾

5.scannerList中剩余的scanner根據(jù)startRow,stopRow將指針seek到正確的位置。

6.將scanners以PriorityQueue的形式組織,優(yōu)先級同樣為CellComparatorImp。

PS:StoreFileComparators.SEQ_ID —— Comparator.comparingLong(HStoreFile::getMaxSequenceId) ?.thenComparing(Comparator.comparingLong(new GetFileSize()).reversed()) ?.thenComparingLong(new GetBulkTime()).thenComparing(new GetPathName())

組建好需要Scanner體系之后,后續(xù)就是讀取流程了。

讀取流程如下圖所示:

RegionScanner主要負責以下功能:

其包含storeHeap與joinedHeap都為KeyValueHeap的對象實例,heap底層是包含了多個StoreScanner組成的PriorityQueue,comparator = CellComparatorImp。向上提供符合條件的整行數(shù)據(jù)的迭代查詢。

1.循環(huán)從storeHeap上獲取cell數(shù)據(jù),以此判斷是否還存在待獲取數(shù)據(jù)。如果沒有,return false。如果有:

2.那么先從storeHeap上獲取family essential相關(guān)的數(shù)據(jù),使用filter進行過濾。如果被過濾,continue loop。如果沒有:

3.那么從joinedHeap上獲取剩余數(shù)據(jù),返回。

StoreScanner主要負責以下功能:

StoreScanner雖然是實現(xiàn)了KeyValueScanner和InternalScanner的類,但主要靠其成員變量heap(KeyValueHeap)來完成必要的操作。heap由多個StoreFileScanner實例按照PriorityQueue組成,comparator = CellComparatorImp。

1.循環(huán)從heap中獲取cell。

2.通過matcher匹配cell獲得返回的MatchCode,不同MatchCode會觸發(fā)不同的操作,見下表。

?3.不停循環(huán),直到數(shù)據(jù)組成整行,向上返回。

StoreScanner中KeyValueHeap的next功能:

storeScanner中的heap.next()究竟做了什么?簡單來說,做了以下兩件事情:1)從current(當前的StoreFileScanner,不在heap中)獲取cell返回2)更新當前current,把current放回heap重新排序,再獲取當前最優(yōu)先的StoreFileScanner作為current。

具體做法如下:

1.從當前的StoreFileScanner current中獲取下一個cell(kvReturn)。再獲取kvReturn往后的第一個cell(kvNext)

2.判斷kvNext是否為空。為空代表當前current讀取完畢,需要從heap中獲取下一個scanner記為current。不為空則

3.從當前heap中獲取第一個scanner,與current 進行對比。判斷它們誰通過peek()獲得的cell key最小,如果scanner更小,那么把current放回heap。重新heap.poll()獲得最新current。

4.返回kvReturn cell。

至此整個HBase的讀路徑分析結(jié)束,留待補充的點:

1.Matcher的實現(xiàn)邏輯分析。

2.BloomFilter的過濾分析。

3.StoreFileScanner以下直到HDFS之間的鏈路分析,中間涉及一個BlockCache。

原文鏈接

本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。?

總結(jié)

以上是生活随笔為你收集整理的HBase读链路分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。