日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

HBase存儲架構(gòu)

 daomucun 2011-07-14

HBase存儲架構(gòu)

1070人閱讀 評論(1) 收藏 舉報

 

英文原文:http://www./2009/10/hbase-architecture-101-storage.html

 

HBase最隱秘的問題之一就是它的數(shù)據(jù)是如何存儲的。雖然大多數(shù)用戶都不會因為這個問題向你抱怨,但是如果你想學(xué)習(xí)哪些高級的配置選項并了解它們的意思,你可能就需要來了解一下這個存儲問題了。“怎樣才能把HBase調(diào)整到最適合我需求的狀態(tài)?”你可能對于這樣一系列類似的問題非常感興趣。那么你就需要繞過這些問題來學(xué)習(xí)HBase的基礎(chǔ)知識。另一個支持你學(xué)習(xí)這些基礎(chǔ)知識的理由是有時候各種各樣你想不到的災(zāi)難需要你恢復(fù)整個HBase

我首先學(xué)習(xí)了HBase中控制各種不同文件的獨立的類,然后根據(jù)我對整個HBase存儲系統(tǒng)的理解在腦海中構(gòu)建HBase架構(gòu)的圖像。但是我發(fā)現(xiàn)想要在頭腦中構(gòu)建出一幅連貫的HBase架構(gòu)圖片很困難,于是我就把它畫了出來。

你可能注意到了這不是一個UML圖或者調(diào)用圖。這個圖混合了類和他們管理控制的文件,將注意力集中到了本文要討論的主題上。后面我將會討論這張圖所涉及到的細節(jié),包括一些配置文件項是如何影響底層的文件存儲系統(tǒng)的。

好,我們現(xiàn)在來分析這張圖里面到底包含了什么。首先HBase操控兩種基本類型的文件,一種用于存儲WALlog,另一種用于存儲具體的數(shù)據(jù)。這兩種文件主要由HRegionServer來管理,但是在有的情況下HMaster會跳過HRegionServer,直接操作這兩種文件。你可能注意到了,這些文件都被存儲在HDFS上面,并且每個文件包含了多個數(shù)據(jù)塊。配置文件中就有一個選項用來調(diào)整系統(tǒng)控制數(shù)據(jù)的大小。我們后面會詳細討論這個問題。

接下來看一下數(shù)據(jù)的大致流程。假設(shè)你需要通過某個特定的RowKey查詢一行記錄,首先Client端會連接Zookeeper Qurom,通過ZookeeperClient能獲知哪個Server管理-ROOT- Region。接著Client訪問管理-ROOT-Server,進而獲知哪個Server管理.META.表。這兩個信息Client只會獲取一次并緩存起來。在后續(xù)的操作中Client會直接訪問管理.META.表的Server,并獲取Region分布的信息。一旦Client獲取了這一行的位置信息,比如這一行屬于哪個Region,Client將會緩存這個信息并直接訪問HRegionServer。久而久之Client緩存的信息漸漸增多,即使不訪問.META.表也能知道去訪問哪個HRegionServer。

注意:當(dāng)HBase啟動的時候HMaster負責(zé)分配RegionHRegionServer,這其中當(dāng)然也包括-ROOT-表和.META.表的Region。

 

接下來HRegionServer打開這個Region并創(chuàng)建一個HRegion對象。當(dāng)HRegion打開以后,它給每個table的每個HColumnFamily創(chuàng)建一個Store實例。每個Store實例擁有一個或者多個StoreFile實例。StoreFileHFile做了輕量級的包裝。除了Store實例以外,每個HRegion還擁有一個MemStore實例和一個HLog實例?,F(xiàn)在我們就可以看看這些實例是如何在一起工作的,遵循什么樣的規(guī)則以及這些規(guī)則的例外。


保留住Put

現(xiàn)在看一下數(shù)據(jù)是怎樣被寫到實際的存儲中去的。Client發(fā)起了一個HTable.put(Put)請求給HRegionServer,HRegionServer會將請求匹配到某個具體的HRegion上面。緊接著的操作時決定是否寫WAL log。是否寫WAL logClient傳遞的一個標志決定,你可以設(shè)置這個標志:Put.writeToWAL(boolean)。WAL log文件是一個標準的Hadoop SequenceFile(現(xiàn)在還在討論是否應(yīng)該把文件格式改成一個更適合HBase的格式)。在文件中存儲了HLogKey,這些Keys包含了和實際數(shù)據(jù)對應(yīng)的序列號,用途是當(dāng)RegionServer崩潰以后能將WAL log中的數(shù)據(jù)同步到永久存儲中去。做完這一步以后,Put數(shù)據(jù)會被保存到MemStore中,同時會檢查MemStore是否已經(jīng)滿了,如果已經(jīng)滿了,則會觸發(fā)一個Flush to Disk的請求。HRegionServer有一個獨立的線程來處理Flush to Disk的請求,它負責(zé)將數(shù)據(jù)寫成HFile文件并存到HDFS上。它也會存儲最后寫入的數(shù)據(jù)序列號,這樣就可以知道哪些數(shù)據(jù)已經(jīng)存入了永久存儲的HDFS中?,F(xiàn)在讓我們來看看這些存儲文件。

 

存儲文件

HBaseHDFS上面的所有文件有一個可配置的根目錄,默認根目錄是/hbase。通過使用hadoopDFS工具就可以看到這些文件夾的結(jié)構(gòu)。

在根目錄下面你可以看到一個.logs文件夾,這里面存了所有由HLog管理的WAL log文件。在.logs目錄下的每個文件夾對應(yīng)一個HRegionServer,每個HRegionServer下面的每個log文件對應(yīng)一個Region。

有時候你會發(fā)現(xiàn)一些oldlogfile.log文件(在大多數(shù)情況下你可能看不到這個文件),這個文件在一種異常情況下會被產(chǎn)生。這個異常情況就是HMasterlog文件的訪問情況產(chǎn)生了懷疑,它會產(chǎn)生一種稱作“log splits”的結(jié)果。有時候HMaster會發(fā)現(xiàn)某個log文件沒人管了,就是說任何一個HRegionServer都不會管理這個log文件(有可能是原來管理這個文件的HRegionServer掛了),HMaster會負責(zé)分割這個log文件(按照它們歸屬的Region),并把那些HLogKey寫到一個叫做oldlogfile.log的文件中,并按照它們歸屬的Region直接將文件放到各自的Region文件夾下面。各個HRegion會從這個文件中讀取數(shù)據(jù)并將它們寫入到MemStore中去,并開始將數(shù)據(jù)Flush to Disk。然后就可以把這個oldlogfile.log文件刪除了。

注意:有時候你可能會發(fā)現(xiàn)另一個叫做oldlogfile.log.old的文件,這是由于HMaster做了重復(fù)分割log文件的操作并發(fā)現(xiàn)oldlogfile.log已經(jīng)存在了。這時候就需要和HRegionServer以及HMaster協(xié)商到底發(fā)生了什么,以及是否可以把old的文件刪掉了。從我目前遇到的情況來看,old文件都是空的并且可以被安全刪除的。

HBase的每個Table在根目錄下面用一個文件夾來存儲,文件夾的名字就是Table的名字。在Table文件夾下面每個Region也用一個文件夾來存儲,但是文件夾的名字并不是Region的名字,而是Region的名字通過Jenkins Hash計算所得到的字符串。這樣做的原因是Region的名字里面可能包含了不能在HDFS里面作為路徑名的字符。在每個Region文件夾下面每個ColumnFamily也有自己的文件夾,在每個ColumnFamily文件夾下面就是一個個HFile文件了。所以整個文件夾結(jié)構(gòu)看起來應(yīng)該是這個樣子的:

/hbase/<tablename>/<encoded-regionname>/<column-family>/<filename>

在每個Region文件夾下面你會發(fā)現(xiàn)一個.regioninfo文件,這個文件用來存儲這個RegionMeta Data。通過這些Meta Data我們可以重建被破壞的.META.表,關(guān)于.regioninfo的應(yīng)用你可以參考HBASE-7HBASE-1867

有一件事情前面一直沒有提到,那就是Region的分割。當(dāng)一個Region的數(shù)據(jù)文件不斷增長并超過一個最大值的時候(你可以配置這個最大值 hbase.hregion.max.filesize),這個Region會被切分成兩個。這個過程完成的非常快,因為原始的數(shù)據(jù)文件并不會被改變,系統(tǒng)只是簡單的創(chuàng)建兩個Reference文件指向原始的數(shù)據(jù)文件。每個Reference文件管理原始文件一半的數(shù)據(jù)。Reference文件名字是一個ID,它使用被參考的Region的名字的Hash作為前綴。例如:1278437856009925445.3323223323。Reference文件只含有非常少量的信息,這些信息包括被分割的原始RegionKey以及這個文件管理前半段還是后半段。HBase使用HalfHFileReader類來訪問Reference文件并從原始數(shù)據(jù)文件中讀取數(shù)據(jù)。前面的架構(gòu)圖只并沒有畫出這個類,因為它只是臨時使用的。只有當(dāng)系統(tǒng)做Compaction的時候原始數(shù)據(jù)文件才會被分割成兩個獨立的文件并放到相應(yīng)的Region目錄下面,同時原始數(shù)據(jù)文件和那些Reference文件也會被清除。

前面dump出來的文件結(jié)構(gòu)也證實了這個過程,在每個Table的目錄下面你可以看到一個叫做compaction.dir的目錄。這個文件夾是一個數(shù)據(jù)交換區(qū),用于存放splitcompact Region過程中生成的臨時數(shù)據(jù)。

 

HFile

現(xiàn)在我們將深入HBase存儲架構(gòu)的核心,探討HBase具體的數(shù)據(jù)存儲文件的結(jié)構(gòu)。HFile就是這個數(shù)據(jù)存儲文件的結(jié)構(gòu)(Ryan Rawson就是靠它揚名立萬的)。創(chuàng)建HFile這樣一個文件結(jié)構(gòu)的目的只有一個:快速高效的存儲HBase的數(shù)據(jù)。HFile是基于Hadoop TFile的(參見 HADOOP-3315)。HFile模仿了Google BigtableSSTable的格式。原先HBase使用HadoopMapFile,但是這種文件已經(jīng)被證明了效率差。

現(xiàn)在讓我們來看看這個文件結(jié)構(gòu)到底是什么樣的。

 

 

 

首先這個文件是不定長的,長度固定的只有其中的兩塊:TrailerFileInfo。正如圖中所示的,Trailer中有指針指向其他數(shù)據(jù)塊的起始點。Index數(shù)據(jù)塊記錄了每個Data塊和Meta塊的起始點。Data塊和Meta塊都是可有可無的,但是對于大部分的HFile,你都可以看到Data塊。

那么每個塊的大小是如何確定的呢?這個值可以在創(chuàng)建一個Table的時候通過HColumnDescriptor(實際上應(yīng)該稱作FamilyDescriptor)來設(shè)定。這里我們可以看一個例子:


{NAME => 'docs', FAMILIES => [{NAME => 'cache', COMPRESSION => 'NONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'false'}, {NAME => 'contents', COMPRESSION => 'NONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'false'}, ...

 

從這里可以看出這是一個叫做docsTable,它有兩個Familycachecontents,這兩個Family對應(yīng)的HFile的數(shù)據(jù)塊的大小都是64K。

關(guān)于如何設(shè)定數(shù)據(jù)塊的大小,我們應(yīng)用一段HFile源碼中的注釋:

我們推薦將數(shù)據(jù)塊的大小設(shè)置為8KB1MB。大的數(shù)據(jù)塊比較適合順序的查詢(比如Scan),但不適合隨機查詢,想想看,每一次隨機查詢可能都需要你去解壓縮一個大的數(shù)據(jù)塊。小的數(shù)據(jù)塊適合隨機的查詢,但是需要更多的內(nèi)存來保存數(shù)據(jù)塊的索引(Data Index),而且創(chuàng)建文件的時候也可能比較慢,因為在每個數(shù)據(jù)塊的結(jié)尾我們都要把壓縮的數(shù)據(jù)流Flush到文件中去(引起更多的Flush操作)。并且由于壓縮器內(nèi)部還需要一定的緩存,最小的數(shù)據(jù)塊大小應(yīng)該在20KB - 30KB左右??赡軓那懊娴拿枋瞿銜l(fā)現(xiàn)數(shù)據(jù)塊(Data Block)是數(shù)據(jù)壓縮的一個單位。后面我們會深入Data Block內(nèi)部去了解它的詳細構(gòu)造。

HBase的配置文件中你會看到一個參數(shù):hfile.min.blocksize.size,這個參數(shù)看上去只會用在數(shù)據(jù)遷移或者通過工具直接創(chuàng)建HFile的過程中。(貌似HBase創(chuàng)建HFile不會使用這個參數(shù),HBase使用的是.META.表中記錄的那個值)。

呼——,到現(xiàn)在為止解釋的還不錯吧。好了,讓我們繼續(xù)。有時候我們可能會想知道一個HFile是否正常以及它里面包含了什么內(nèi)容。沒問題,已經(jīng)有一個應(yīng)用程序來做這件事了。

HFile.main()本身就提供了一個用來dump HFile的工具。

 

 

這里有一個dump文件的例子:

 

 

 

第一部分是存儲具體數(shù)據(jù)的KeyValue對,每個數(shù)據(jù)塊除了開頭的Magic以外就是一個個KeyValue對拼接而成。后面會詳細介紹每個KeyValue對的內(nèi)部構(gòu)造。第二部分是Tailer塊的具體內(nèi)容,最后一部分是FileInfo塊的具體內(nèi)容。Dump HFile還有一個作用就是檢查HFile是否正常。

 

KeyValue

HFile里面的每個KeyValue對就是一個簡單的byte數(shù)組。但是這個byte數(shù)組里面包含了很多項,并且有固定的結(jié)構(gòu)。我們來看看里面的具體結(jié)構(gòu):

 

開始是兩個固定長度的數(shù)值,分別表示Key的長度和Value的長度。緊接著是Key,開始是固定長度的數(shù)值,表示RowKey的長度,緊接著是RowKey,然后是固定長度的數(shù)值,表示Family的長度,然后是Family,接著是Qualifier,然后是兩個固定長度的數(shù)值,表示Time StampKey Type。Value部分沒有這么復(fù)雜的結(jié)構(gòu),就是純粹的數(shù)據(jù)。

java.org.apache.hadoop.hbase.KeyValue是用來處理這個KeyValue,你可能會發(fā)現(xiàn)在這個類里面有兩個方法:getKeygetRowgetKey當(dāng)然是用來獲取Key的內(nèi)容,那么getRow是什么?其實是用來獲取RowKey的。RowKey不是HBase的基本元素嗎?是的,這個類已經(jīng)不是純粹的Key&Value處理,它已經(jīng)打上了HBase的烙印。

好了,這篇文章就到此為止了,它對HBase的存儲架構(gòu)做了一個大致的介紹。希望這篇文章對于那些想更深入的挖掘HBase細節(jié)的人來說,能作為一個起點。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多