HBase(十)架構(gòu)和內(nèi)部實現(xiàn)

      網(wǎng)友投稿 629 2025-04-02

      Hbase繼承BigTable,采用LSM樹(Log-Structured Merge Tree)結(jié)構(gòu)存儲,與RDBMS常用的B+trees不同。

      B+trees能通過主鍵對記錄進行高效插入、查詢、刪除。是一個動態(tài)、多層、有上下界的索引。分段B+trees效果好于二叉樹的數(shù)據(jù)劃分。B+trees因為葉子節(jié)點相互連接且按主鍵有序,所以能提供范圍掃描功能,避免了遍歷操作。B+trees是順序的把表重寫,表的范圍查詢是磁盤的多段連續(xù)讀取。B+trees每次查找需要訪問磁盤log(N)次,所以主要受限于磁盤尋道速度。

      LSM樹組織數(shù)據(jù)方式不同,輸入數(shù)據(jù)首先被存儲在日志文件中,文件中的數(shù)據(jù)完全有序。日志被修改時,對應(yīng)的更新會先保存在內(nèi)存中來加速查詢。內(nèi)存在多次數(shù)據(jù)修改后逐漸沾滿,LSM樹會把有序的“鍵-數(shù)據(jù)記錄”寫入磁盤,并創(chuàng)建一個新的數(shù)據(jù)存儲文件,持久化后,內(nèi)存中數(shù)據(jù)可以清空。所有節(jié)點都是滿的并按頁存儲,修改數(shù)據(jù)文件的操作通過滾動合并完成,即現(xiàn)有的頁與內(nèi)存flush的數(shù)據(jù)混合在一起管理,直到填滿容量。多次數(shù)據(jù)刷寫之后會創(chuàng)建許多數(shù)據(jù)存儲文件,后臺會自動將大量小文件聚合成大文件。查詢數(shù)據(jù)時,首先查找內(nèi)存,然后查找磁盤。數(shù)據(jù)刪除只是會建一個標(biāo)記,查找會跳過標(biāo)記的數(shù)據(jù),頁重寫時,這些刪除標(biāo)記的鍵才會被刪除。

      LSM和B+對比看,沒有太多修改時,B+樹表現(xiàn)的很好,因為這些修改要求執(zhí)行高代價的優(yōu)化操作以保證查詢能在有限時間內(nèi)完成。在隨機位置添加的數(shù)據(jù)越多,速度越快,這些頁成為碎片的速度就越快,用戶寫入速度可能比優(yōu)化后重寫文件的處理速度越快。更新和刪除都需要磁盤尋道,所以就會限制于磁盤速度。LSM樹利用內(nèi)容和日志文件把隨機寫變成順序?qū)懀x寫?yīng)毩ⅲ@兩種操作間沒有沖突。存儲的數(shù)據(jù)布局較優(yōu),查詢一個鍵所需要的磁盤尋道次數(shù)在一個可預(yù)測的范圍內(nèi),且讀取與該鍵連續(xù)的任意數(shù)量的記錄都不會引發(fā)任何額外的磁盤尋道。基于LSM樹的系統(tǒng)強調(diào)的是成本透明:假設(shè)有5個存儲文件,一個訪問最多需要5個磁盤尋道。B+樹結(jié)構(gòu)的RDBMS,沒辦法確定一次查詢需要的磁盤尋道次數(shù)。

      Hbase底層文件存儲在HDFS中,實際的數(shù)據(jù)文件可能被HDFS分割成小塊。Client查找行健是通過zookeeper完成,先查找ZK中-ROOT-的region server,從-ROOT-查找.META.表,從META表獲取行健相關(guān)的region server。這個過程會緩存,下載client查找不用再次查找zk。

      Client發(fā)起寫請求時,請求會轉(zhuǎn)交對應(yīng)的HRegion實例處理。首先決定是否寫入HLog類實現(xiàn)的WAL中。WAL是Hadoop SequenceFile,存儲了HLogKey實例,鍵包括序列號和實際數(shù)據(jù),服務(wù)器崩潰時可以恢復(fù)還沒有持久化的數(shù)據(jù)。數(shù)據(jù)寫入WAL后,數(shù)據(jù)會放到MemStore中,同時檢查MemStore是否寫滿,滿了就會刷寫到磁盤中,flush由另一個HRegionServer線程處理。會寫成一個新的HFile,同時保存最后寫入的序列號,系統(tǒng)知道持久化到什么位置了。

      Hbase在HDFS中的根目錄可配置,默認(rèn)是/hbase,可以配置不同的根目錄,使不同的Hbase實例共享HDFS,可以用hadoop dfs –lsr來查看Hbase目錄結(jié)構(gòu)。

      pmapp:~> hadoop dfs -lsr /hbase | head -100

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 12:06 /hbase/-ROOT-

      -rw-r--r-- 3 acrosspm supergroup 728 2015-11-26 19:18 /hbase/-ROOT-/.tableinfo.0000000001

      drwxr-xr-x - acrosspm supergroup 0 2015-11-26 19:18 /hbase/-ROOT-/.tmp

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 16:57 /hbase/-ROOT-/70236052

      drwxr-xr-x - acrosspm supergroup 0 2015-11-26 19:18 /hbase/-ROOT-/70236052/.oldlogs

      -rw-r--r-- 3 acrosspm supergroup 421 2015-11-26 19:18 /hbase/-ROOT-/70236052/.oldlogs/hlog.1448536690090

      -rw-r--r-- 3 acrosspm supergroup 109 2015-11-26 19:18 /hbase/-ROOT-/70236052/.regioninfo

      drwxr-xr-x - acrosspm supergroup 0 2015-12-27 19:43 /hbase/-ROOT-/70236052/.tmp

      drwxr-xr-x - acrosspm supergroup 0 2015-12-27 19:43 /hbase/-ROOT-/70236052/info

      -rw-r--r-- 3 acrosspm supergroup 1486 2015-12-27 19:43 /hbase/-ROOT-/70236052/info/9b55c4386f4740e4ab8ae223e59a3b1b

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 12:06 /hbase/.META.

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 16:57 /hbase/.META./1028785192

      drwxr-xr-x - acrosspm supergroup 0 2015-11-26 19:18 /hbase/.META./1028785192/.oldlogs

      -rw-r--r-- 3 acrosspm supergroup 134 2015-11-26 19:18 /hbase/.META./1028785192/.oldlogs/hlog.1448536690294

      -rw-r--r-- 3 acrosspm supergroup 111 2015-11-26 19:18 /hbase/.META./1028785192/.regioninfo

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 13:15 /hbase/.META./1028785192/.tmp

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 13:15 /hbase/.META./1028785192/info

      -rw-r--r-- 3 acrosspm supergroup 1235 2016-01-04 13:15 /hbase/.META./1028785192/info/0994f57412b54ada8f9408ebdc454e10

      -rw-r--r-- 3 acrosspm supergroup 318056 2016-01-04 06:00 /hbase/.META./1028785192/info/5fdb37189fe04f3999c2dcd69e7b676a

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 11:05 /hbase/.META./1028785192/recovered.edits

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 15:43 /hbase/.archive

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 15:43 /hbase/.archive/H_20160103_0000

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 15:43 /hbase/.archive/H_20160103_0000/b9cc9e6e5b4cd2d2c01e3090ed300340

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 15:43 /hbase/.archive/H_20160103_0000/b9cc9e6e5b4cd2d2c01e3090ed300340/family0

      -rw-r--r-- 3 acrosspm supergroup 1324 2016-01-04 15:43 /hbase/.archive/H_20160103_0000/b9cc9e6e5b4cd2d2c01e3090ed300340/family0/b5c3a8cf77e94e2badb298d807d29639

      drwxr-xr-x - acrosspm supergroup 0 2015-12-14 09:49 /hbase/.corrupt

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 15:56 /hbase/.logs

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 15:56 /hbase/.logs/11.12.13.253,15241,1451116615973

      -rw-r--r-- 3 acrosspm supergroup 0 2015-12-26 15:56 /hbase/.logs/11.12.13.253,15241,1451116615973/11.12.13.253%2C15241%2C1451116615973.1451116616553

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 14:59 /hbase/.logs/pmeam1,15241,1451116615669

      -rw-r--r-- 3 acrosspm supergroup 162986 2016-01-04 13:59 /hbase/.logs/pmeam1,15241,1451116615669/pmeam1%2C15241%2C1451116615669.1451887185552

      -rw-r--r-- 3 acrosspm supergroup 0 2016-01-04 14:59 /hbase/.logs/pmeam1,15241,1451116615669/pmeam1%2C15241%2C1451116615669.1451890785896

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 14:57 /hbase/.logs/pmweb,15241,1451116616005

      -rw-r--r-- 3 acrosspm supergroup 1380486 2016-01-04 13:57 /hbase/.logs/pmweb,15241,1451116616005/pmweb%2C15241%2C1451116616005.1451887044332

      -rw-r--r-- 3 acrosspm supergroup 0 2016-01-04 14:57 /hbase/.logs/pmweb,15241,1451116616005/pmweb%2C15241%2C1451116616005.1451890644505

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 15:07 /hbase/.oldlogs

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 12:15 /hbase/.tmp

      drwxr-xr-x - acrosspm supergroup 0 2015-12-11 11:17 /hbase/12H_20151203_0000

      -rw-r--r-- 3 acrosspm supergroup 697 2015-12-03 12:15 /hbase/12H_20151203_0000/.tableinfo.0000000001

      drwxr-xr-x - acrosspm supergroup 0 2015-12-03 12:15 /hbase/12H_20151203_0000/.tmp

      drwxr-xr-x - acrosspm supergroup 0 2015-12-11 11:17 /hbase/12H_20151203_0000/e865997cef7a7975e7bc201804a0bde6

      -rw-r--r-- 3 acrosspm supergroup 258 2015-12-03 12:15 /hbase/12H_20151203_0000/e865997cef7a7975e7bc201804a0bde6/.regioninfo

      drwxr-xr-x - acrosspm supergroup 0 2015-12-04 17:43 /hbase/12H_20151203_0000/e865997cef7a7975e7bc201804a0bde6/family0

      -rw-r--r-- 3 acrosspm supergroup 393668 2015-12-04 17:43 /hbase/12H_20151203_0000/e865997cef7a7975e7bc201804a0bde6/family0/321934dda7704c8ebe20f6aa80eb67f6

      drwxr-xr-x - acrosspm supergroup 0 2015-12-11 11:17 /hbase/12H_20151204_0000

      -rw-r--r-- 3 acrosspm supergroup 697 2015-12-04 12:15 /hbase/12H_20151204_0000/.tableinfo.0000000001

      drwxr-xr-x - acrosspm supergroup 0 2015-12-04 12:15 /hbase/12H_20151204_0000/.tmp

      drwxr-xr-x - acrosspm supergroup 0 2015-12-11 11:17 /hbase/12H_20151204_0000/b983a372d5eebc449cfcf89fb0c49070

      -rw-r--r-- 3 acrosspm supergroup 258 2015-12-04 12:15 /hbase/12H_20151204_0000/b983a372d5eebc449cfcf89fb0c49070/.regioninfo

      drwxr-xr-x - acrosspm supergroup 0 2015-12-05 18:43 /hbase/12H_20151204_0000/b983a372d5eebc449cfcf89fb0c49070/family0

      -rw-r--r-- 3 acrosspm supergroup 413433 2015-12-05 18:43 /hbase/12H_20151204_0000/b983a372d5eebc449cfcf89fb0c49070/family0/f8009c70f33b41a8a44d1ad3a7f2efab

      ……

      可以看到文件有兩類,一類在根目錄下,一類在表目錄下。

      pmapp:~> hadoop dfs -ls /hbase/

      Found 347 items

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 12:06 /hbase/-ROOT-

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 12:06 /hbase/.META.

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 16:00 /hbase/.archive

      drwxr-xr-x - acrosspm supergroup 0 2015-12-14 09:49 /hbase/.corrupt

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 15:56 /hbase/.logs

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 15:59 /hbase/.oldlogs

      drwxr-xr-x - acrosspm supergroup 0 2016-01-04 12:15 /hbase/.tmp

      drwxr-xr-x - acrosspm supergroup 0 2015-12-04 14:57 /hbase/WW_20151123_0000

      drwxr-xr-x - acrosspm supergroup 0 2015-12-11 11:17 /hbase/WW_20151130_0000

      ……

      .logs

      目錄下存著WAL文件,對每個HRegionServer,日志目錄都包含一個對應(yīng)的子目錄,每個子目錄下有多個HLog文件(滾動日志),一個region server的所有region共享一組HLog文件。

      HDFS使用內(nèi)置的append機制來追加寫入文件,所以只有等文件大小達到一個完整的塊時,文件對用戶才是可見的,包括hadoopdfs –lsr命令,所以最新創(chuàng)建的log文件大小是0。日志滾動后,日志文件被關(guān)閉,HDFS才列出其正確的大小,下一個日志大小又從0開始了。滾動默認(rèn)是1小時,通過hbase.regionserver.logroll.period配置。

      所有修改都持久化到存儲文件后,日志文件會反倒根目錄下的.oldlogs目錄。在hbase.master.logcleaner.ttl屬性時間出發(fā)后(默認(rèn)10分鐘),舊日志文件會被master刪除。master默認(rèn)每分鐘會檢查一下這些文件,間隔是通過hbase.master.cleaner.interval配置的。

      -rw-r--r-- 3 acrosspm supergroup 38 2015-11-26 19:18 /hbase/hbase.id

      -rw-r--r-- 3 acrosspm supergroup 3 2015-11-26 19:18 /hbase/hbase.version

      這兩個文件存儲集群唯一ID和文件格式的版本信息

      splitlog和corrupt

      存儲日志拆分過程中產(chǎn)生的中間拆分文件和損壞的文件

      Hbase的每張表都有自己的目錄,目錄位于根目錄,每張表都包含一個.tableinfo的頂層文件,該文件存儲表對應(yīng)序列化后的HTableDescriptor,包括了表和列族的定義,內(nèi)容可以被讀取。

      .tmp目錄包含一些臨時數(shù)據(jù),如當(dāng)心的.tableinfo文件生成時的臨時數(shù)據(jù)就存在這個目錄

      每個表目錄里面,表模式中每個列族都有一個單獨的目錄,目錄名字的一部分是region名字的MD5值,是編碼region名得到的。

      pmapp:~> hadoop dfs -lsr /hbase/W_20151026_0000

      -rw-r--r-- 3 acrosspm supergroup 693 2015-12-15 11:24 /hbase/W_20151026_0000/.tableinfo.0000000001

      drwxr-xr-x - acrosspm supergroup 0 2015-12-15 11:24 /hbase/W_20151026_0000/.tmp

      drwxr-xr-x - acrosspm supergroup 0 2015-12-26 11:11 /hbase/W_20151026_0000/9740e64a90d75d13a85b83c470a69fd3

      -rw-r--r-- 3 acrosspm supergroup 252 2015-12-15 11:24 /hbase/W_20151026_0000/9740e64a90d75d13a85b83c470a69fd3/.regioninfo

      drwxr-xr-x - acrosspm supergroup 0 2015-12-18 11:50 /hbase/W_20151026_0000/9740e64a90d75d13a85b83c470a69fd3/family0

      -rw-r--r-- 3 acrosspm supergroup 3671703 2015-12-18 11:50 /hbase/W_20151026_0000/9740e64a90d75d13a85b83c470a69fd3/family0/3838fd70dcd3411f8b5437cfc1abc356

      MD5散列是為了滿足文件系統(tǒng)的命名規(guī)則,避免任意的特殊符號。region文件的總體結(jié)構(gòu)是://///

      .regioninfo文件

      包含了對應(yīng)region 的HRegionInfo實例序列化后的信息,與.tableinfo文件類似,都可以通過外部工具查看region的相關(guān)信息,如hbase的hbck工具就是用它檢查并生成元數(shù)據(jù)表中丟失的條目。

      .tmp目錄是按需創(chuàng)建的,存放臨時文件,如一次合并的重寫文件,如果這個過程完成,這些臨時生成的文件通常會移到region目錄中。

      WAL回放時,任何未提交的修改都會寫入每個region的一個單獨的文件中,如果日志拆分已經(jīng)完成,這些文件會被自動移到臨時的recovered.edits目錄中。當(dāng)region被打開時,region server會看到需要恢復(fù)的文件,并回放其中響應(yīng)的條目。WAL拆分和region 的拆分有明顯的區(qū)別,有時很難區(qū)分文件系統(tǒng)中的文件名和目錄名,因為他們名稱中都有拆分的字樣。

      所以,如果region目錄中沒有.tmp目錄,就說明這個region還沒有被壓縮過;如果沒有recovered.edits目錄,就以為這WAL還沒有進行過回放。

      一個region超過配置的閾值(hbase.hregion.max.filesize),region就會拆分,region server在父目錄中創(chuàng)建splits目錄,臨時存放兩個子region 的相關(guān)的數(shù)據(jù),接下來會關(guān)閉這個region,不再接受新的請求。在目錄下會使用多線程創(chuàng)建region必要的目錄結(jié)構(gòu)和文件。如果拆分成功,會移到表目錄中,形成兩個新的region,每region 是原來region的一半。.META.表中父region的狀態(tài)會被更新,表示現(xiàn)在拆分的節(jié)點和子節(jié)點是什么。以上過程可以避免父region被重新意外打開。

      兩個子region都準(zhǔn)備好后,會被同一個服務(wù)器并行打開,打開的過程包括更新.META.表,這兩個region上線并接受請求。初始化兩個region后會對region內(nèi)容進行合并操作,在替換引用文件前會把父region的存儲文件異步重寫到兩個子region中,以上過程會在子region 的.tmp目錄中執(zhí)行。一旦生成了重寫之后的文件,會自動取代引用文件。

      最后,父region會被clear,即在.META.表匯總刪除,在磁盤上的所有文件都被刪除。最后通知master拆分,然后可能由于負(fù)載均衡把新的region移動到其他的region server上。

      整個拆分的過程中,所有的步驟都在zookeeper中進行跟蹤,所以一個服務(wù)器宕機后,其他進程也可以知道這個region 的狀態(tài)。

      memstore不斷刷寫,會生成很多磁盤文件,當(dāng)數(shù)目達到閾值,合并操作就會觸發(fā),把它們合并成若干個大文件。這個過程會持續(xù)到文件體積達到最大存儲文件大小,觸發(fā)一個region拆分。

      合并分兩種,minor和major。

      minor合并負(fù)責(zé)重寫最后生成的幾個文件到一個更大的文件中,文件數(shù)量是hbase.hstore.compaction.min配置的,默認(rèn)=3,且最小值需要>=2,過大的數(shù)字會延遲minor操作,帶來更大的壓縮資源消耗和時間。最大可以處理的文件數(shù)量默認(rèn)是10,通過hbase.hstore.compaction.max配置。hbase.hstore.compaction.min.size(默認(rèn)為memstore刷寫大小)和hbase.hstore.compaction.max.size(默認(rèn)為Long.MAX_VALUE)配置項可以過濾需要合并的文件列表,任何超過這個范圍大小的文件都會排除在外。其中最小文件大小,是一個閾值,而不是針對每個文件的限制,小于這個閾值的文件也可能會包含在內(nèi)。 使用hbase.hstore.compaction.ratio(默認(rèn)是1.2,即120%)配置,確保在選擇過程中有足夠的文件,評估是按老到新的順序進行,保證舊文件會先被合并。

      Major合并,是把所有的文件壓縮成一個單獨的文件,在壓縮檢查時,系統(tǒng)會判斷執(zhí)行那種合并。在memstore被flush到磁盤后會觸發(fā)這個檢查,或在shell中compact和major compact命令手動觸發(fā)檢查,或者是java api調(diào)用觸發(fā)等等,region server會調(diào)用CompactionChecker類的實現(xiàn),以一個固定的周期觸發(fā)檢查,這個周期由hbase.server.thread.wakefrequency控制。注意這個周期要乘以1000,由hbase.server.thread.wakefrequency.multiplier參數(shù)配置,避免任務(wù)執(zhí)行太頻繁。

      服務(wù)器會先檢查上次運行到現(xiàn)在是否達到hbase.hregion.majorcompaction,默認(rèn)為24小時的配置,如果沒達到major合并周期的時間,系統(tǒng)就會執(zhí)行minor合并。hbase通過參數(shù)hbase.hregion.majorcompaction.jitter(默認(rèn)為0.2,即20%)進行時間周期的抖動,避免所有region在統(tǒng)一時間進行major合并。

      當(dāng)minor合并包括所有的存儲文件,且所有文件均未達到設(shè)置的每次壓縮的最大文件數(shù)時,minor合并可能被提升成major合并。 和compaction的主要區(qū)別是major-compaction會回收系統(tǒng)刪除的數(shù)據(jù)和TTL到期的數(shù)據(jù)。

      Hbase存儲數(shù)據(jù)是基于HFile的,而HFile是基于Hadoop的TFile類,并參考google的BigTable架構(gòu)使用SSTable格式。

      文件長度是可變的,唯一固定的塊是File info和Trailer。Trailer塊有指向其他塊的指針。它是在持久化數(shù)據(jù)到文件結(jié)束時寫入的,寫入后即確定為不可變的數(shù)據(jù)存儲文件。Index塊記錄Data和Meta塊的偏移量。Date和Meta塊實際上是可選的,但是Data塊實際上一般是有的。

      塊大小由HColumnDescriptor配置,默認(rèn)是64KB,一般應(yīng)用推薦在8K到1M之間,塊越小,隨機訪問越好,但是需要更多內(nèi)存來存儲塊索引,創(chuàng)建過程也會變慢。塊越大,越利于順序訪問。

      每個塊都包含一個Magic頭部和一定數(shù)量的序列化的KeyValue實例,如果沒有使用壓縮,每個塊大小和配置的塊大小差不多,但是如果存儲的KeyValue大于塊大小配置,也會寫入。

      Hbase塊和Hadoop塊不相關(guān),HDFS不知道Hbase存儲的是什么,看到的其實是二進制文件。

      Hbase提供了一個直接訪問HFile的工具:

      pmapp:~> hbase org.apache.hadoop.hbase.io.hfile.HFile

      16/01/05 15:28:47 INFO util.ChecksumType: Checksum using org.apache.hadoop.util.PureJavaCrc32

      usage: HFile [-a] [-b] [-e] [-f

      ] [-k] [-m] [-p] [-r

      ] [-s] [-v]

      [-w

      ]

      -a,--checkfamily Enable family check

      -b,--printblocks Print block index meta data

      -e,--printkey Print keys

      -f,--file

      File to scan. Pass full-path; e.g.

      hdfs://a:9000/hbase/.META./12/34

      -k,--checkrow Enable row order check; looks for out-of-order

      keys

      -m,--printmeta Print meta data of file

      -p,--printkv Print key/value pairs

      -r,--region

      Region to scan. Pass region name; e.g. '.META.,,1'

      -s,--stats Print statistics

      -v,--verbose Verbose output; emits file and meta data

      delimiters

      -w,--seekToRow

      Seek to this row and print all the kvs for this

      row only

      pmapp:~> hbase org.apache.hadoop.hbase.io.hfile.HFile -v -m -p -f /hbase/12H_20151210_0000/e045ac641e54fa46c1746305bc410e0e/family0/c1cfc527eabc431eb1179802f5cc0e62

      16/01/05 15:32:03 INFO util.ChecksumType: Checksum using org.apache.hadoop.util.PureJavaCrc32

      Scanning -> /hbase/12H_20151210_0000/e045ac641e54fa46c1746305bc410e0e/family0/c1cfc527eabc431eb1179802f5cc0e62

      16/01/05 15:32:04 INFO hfile.CacheConfig: Allocating LruBlockCache with maximum size 733.4m

      16/01/05 15:32:04 ERROR metrics.SchemaMetrics: Inconsistent configuration. Previous configuration for using table name in metrics: true, new configuration: false

      K: 12H_20151210_0000_1449720912058111912913914725632/family0:column0/1449721233852/Put/vlen=1750/ts=0 V: PK\x03\x04\x14\x00\x08\x08\x08\x00\x90b\x8AG\x00\x00\x00\x00\x00\x00\x00\x00\x00\……

      Block index size as per heapsize: 1208

      reader=/hbase/12H_20151210_0000/e045ac641e54fa46c1746305bc410e0e/family0/c1cfc527eabc431eb1179802f5cc0e62,

      compression=none,

      cacheConf=CacheConfig:enabled [cacheDataOnRead=true] [cacheDataOnWrite=false] [cacheIndexesOnWrite=false] [cacheBloomsOnWrite=false] [cacheEvictOnClose=false] [cacheCompressed=false],

      firstKey=12H_20151210_0000_1449720912058111912913914725632/family0:column0/1449721233852/Put,

      lastKey=12H_20151210_0000_145040919421611191291392315189/family0:column0/1451446709688/Put,

      avgKeyLen=74,

      avgValueLen=2598,

      entries=153,

      length=411583

      Trailer:

      fileinfoOffset=411028,

      loadOnOpenDataOffset=410364,

      dataIndexCount=7,

      metaIndexCount=0,

      totalUncomressedBytes=410943,

      entryCount=153,

      compressionCodec=NONE,

      uncompressedDataIndexSize=616,

      numDataIndexLevels=1,

      firstDataBlockOffset=0,

      lastDataBlockOffset=409477,

      comparatorClassName=org.apache.hadoop.hbase.KeyValue$KeyComparator,

      majorVersion=2,

      minorVersion=0

      Fileinfo:

      DATA_BLOCK_ENCODING = NONE

      DELETE_FAMILY_COUNT = \x00\x00\x00\x00\x00\x00\x00\x00

      EARLIEST_PUT_TS = \x00\x00\x01Q\x8A\x19\xAAb

      MAJOR_COMPACTION_KEY = \xFF

      MAX_SEQ_ID_KEY = 1263241

      TIMERANGE = 1449720916578....1451446709688

      hfile.AVG_KEY_LEN = 74

      hfile.AVG_VALUE_LEN = 2598

      hfile.LASTKEY = \x00012H_20151210_0000_145040919421611191291392315189\x07family0column0\x00\x00\x01Q\xF0\xF7-\xB8\x04

      Mid-key: \x00112H_20151210_0000_1449720924811111912913914725632\x07family0column0\x00\x00\x01Q\x8A\x1E\x98\x0B\x04

      Bloom filter:

      Not present

      Delete Family Bloom filter:

      Not present

      Scanned kv count -> 153

      HFile中每個KeyValue其實是一個低級的字節(jié)數(shù)組,允許零復(fù)制訪問數(shù)據(jù)。

      鍵中包含了指定單元的全維度內(nèi)容。包含了行健、列族名、列限定符等。所以key在value小的時候會造成較大的負(fù)擔(dān),如果使用的值比較短,盡量保持一個比較短的鍵。另外,壓縮也可以緩解這個問題。

      Hbase的HLog相當(dāng)于一個regionserver的日志中心,所有region共享。這部分涉及是參考BigTable論文的,如果每個region一個WAL,會產(chǎn)生大量文件,底層文件系統(tǒng)實現(xiàn)起來會有大量的磁盤尋道,性能會降低。

      數(shù)據(jù)請求RPC到達服務(wù)端后,先寫入HLOG,再寫入MemStore。

      HRegion實例化時,HLog實例會作為構(gòu)造函數(shù)的參數(shù)傳入。HLog核心功能是append()方法。Put、Delete等功能可以設(shè)置是否寫WAL,除非大批量導(dǎo)入的場景,一般還是要開啟WAL的。HLog通過一個AtomicLong的序列號,保證順序?qū)懭搿?/p>

      WAL是Hadoop的SquenceFile格式,鍵值對中,值是client發(fā)送的修改請求,封裝為WALEdit類,鍵是HLogKey實例,KeyValue的歸屬,如region和表名,都存在這個類中,也會包含上面說的序列號和寫入時間。

      WAL的異步寫入控制是LogSyncer類,這個類實例會單獨運行在一個實例中。

      WAL日志滾動控制為LogRoller類,可以配置hbase.regionserver.logroll.period參數(shù)控制滾動間隔,默認(rèn)是1個小時。hbase.regionserver.logroll.multiplier參數(shù)控制達到塊大小的百分比發(fā)生滾動,默認(rèn)是0.95。及hbase.regionserver.hlog.blocksize參數(shù)控制塊大小。

      HLog.cleanOldLogs()會定期檢查存儲文件和WAL中的序列號,定期清理WAL。

      由于WAL被所有region共享,所以,數(shù)據(jù)恢復(fù)會分成兩個步驟,日志拆分和數(shù)據(jù)恢復(fù)執(zhí)行。

      拆分由ServerShutdownHandler類完成,就是把共享的log拆分為每個region一個log。hbase.master.distributed.log.splitting參數(shù)控制是否啟用分布式拆分,在單點拆分下,是多線程處理的,線程數(shù)默認(rèn)是3,由hbase.regionserver.hlog.splitlog.writer.threads參數(shù)控制。

      拆分首先把數(shù)據(jù)改動寫入根目錄的splitlog文件夾,包含的元信息寫在路徑和文件名中。

      不能解析的log會放到.corrupt文件夾,可以設(shè)置是否靜默異常,如果非靜默,拋出異常整個過程就會停止。

      拆分最后,每個region對應(yīng)的文件會移到對應(yīng)的region目錄。

      region打開后先檢查recovered.edits目錄,如果存在就會打開其中的文件,讀取變更記錄。其中記錄的序號小于等于存儲文件中的序號,都會被拋棄。整個目錄所有文件都處理完,整個目錄就會刪除。

      如果中間遇到問題,還是同樣靜默配置的原理,要么終止過程,要么其文件會被修改后綴名供人工檢查。

      災(zāi)備場景下,也是通過WAL的方式同步數(shù)據(jù)。日志同步,數(shù)據(jù)異步,通過zk跟蹤。默認(rèn)機制挑選10%的機器進行復(fù)制,如集群100臺,有1臺機器負(fù)責(zé)同步。

      Hbase內(nèi)部是三層B+tree的索引方式,ROOT region 能映射2:6 [1] 105 個.META. region,

      依次能映射總的6:9x1010 個user region,意味著大約是1:8x1019(264) 字節(jié)用戶數(shù)據(jù)(即214PB)。

      client 會將查詢過的位置信息保存緩存起來,緩存不會主動失效,因此如果client 上的緩存全部失效,則需要進行6 次網(wǎng)絡(luò)來回,才能定位到正確的region(其中三次用來發(fā)現(xiàn)緩存失效,另外三次用來獲取位置信息)。

      Hbase內(nèi)部的數(shù)據(jù)查詢由QueryMatcher和ColumnTracker來實現(xiàn),一個是精確匹配列,一個是匹配所有列。

      匹配可以使用布隆過濾器和時間戳的方式先過濾大部分?jǐn)?shù)據(jù)。

      Scan操作通過RegionScanner實現(xiàn),該類為每個store(每個store是一個列族)配一個StoreScanner,會掃描MemStore和存儲文件。StoreScanner通過QueryMatcher描述具體哪個KeyValue要包含進來。

      RegionScanner內(nèi)部用KeyValueHeap類,按時間戳排序來處理存儲掃描器,StoreScanner也同樣是復(fù)用這個類對存儲排序。

      get的內(nèi)部實現(xiàn),實際上就是個單步scan。

      region狀態(tài)變更由Master跟蹤,使用AssignmentManager類管理。

      狀態(tài)列表如下:

      HBase(十)架構(gòu)和內(nèi)部實現(xiàn)

      Offline The region is offline.

      Pending Open A request to open the region was sent to the server.

      Opening The server has started opening the region.

      Open The region is open and fully operational.

      Pending Close A request to close the region has been sent to the server.

      Closing The server is in the process of closing the region.

      Closed The region is closed.

      Splitting The server started splitting the region.

      Split The region has been split by the server.

      zk中根目錄由zookeeper.znode.parent參數(shù)配置,默認(rèn)為/hbase。

      [zk: pmapp:15248(CONNECTED) 1] ls /hbase

      [splitlog, online-snapshot, unassigned, backup-masters, root-region-server, rs, table92, draining, table, hbaseid, shutdown]

      /hbase/hbaseid

      與hbase.id文件內(nèi)容相同

      /hbase/master

      master服務(wù)器

      /hbase/replication

      副本信息

      /hbase/root-region-server

      -ROOT- region所在的region server機器名

      /hbase/rs

      所有region server的根節(jié)點,每個znode都是臨時節(jié)點,且node名是region server名稱

      /hbase/shutdown

      跟蹤集群狀態(tài),包括集群啟動時間、集群關(guān)閉

      /hbase/splitlog

      數(shù)據(jù)恢復(fù)的日志拆分步驟的相關(guān)信息的父節(jié)點

      /hbase/table

      表被禁用時,信息回添加到這個node,表名是新建的znode名,content是DISABLED。

      /hbase/unassigned

      AssignmentManager類用來跟蹤region生命周期,包含not open的region,znode名是region的hash。

      轉(zhuǎn)載請注明出處:華為云博客 https://portal.hwclouds.com/blogs

      hbase

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:要從上面弄田字格,怎么弄?(怎么在文檔里弄田字格)
      下一篇:表格中如何加斜線填文字(在表格中加斜線后怎么填寫)
      相關(guān)文章
      亚洲国产精品无码观看久久| 亚洲国产精品无码久久久不卡 | 亚洲AV乱码久久精品蜜桃| 亚洲精品自偷自拍无码| 亚洲日本在线电影| 亚洲日本在线电影| 亚洲一区精彩视频| 久久久久se色偷偷亚洲精品av| 亚洲国产成人精品无码区在线网站| 亚洲美女激情视频| 久久亚洲美女精品国产精品 | 亚洲AV香蕉一区区二区三区| 亚洲熟妇无码AV不卡在线播放| 亚洲中文无码永久免| 亚洲AV无码国产剧情| 四虎精品亚洲一区二区三区| 亚洲成片观看四虎永久| 亚洲人成人无码网www国产| 亚洲日韩中文字幕日韩在线| 国产亚洲大尺度无码无码专线 | 亚洲一区爱区精品无码| 亚洲国产成人高清在线观看| 久久精品国产亚洲AV麻豆王友容 | 亚洲国产高清在线| 亚洲春色在线观看| 亚洲第一男人天堂| 久久亚洲中文无码咪咪爱| 亚洲成av人片在线观看天堂无码| 亚洲午夜爱爱香蕉片| 亚洲色无码一区二区三区| 亚洲bt加勒比一区二区| 亚洲白色白色在线播放| 亚洲va在线va天堂成人| 亚洲Av永久无码精品一区二区| 亚洲 自拍 另类小说综合图区| 国产亚洲精品a在线观看| 亚洲一区二区三区乱码A| 亚洲成A人片在线观看WWW| 亚洲综合久久成人69| 日本亚洲免费无线码| 亚洲AV无码乱码精品国产|