《HBase权威指南》读书笔记(一)
第8章 架構
8.1 數據查找和傳輸
8.1.1 B+樹
B樹的一些特性使其能夠通過主鍵對記錄進行高效插入、査找以及刪除。它表示為一個動態、多層并有上下界的索引。同時要注意維護每一段(也被稱作頁表)所包含的主鍵數目。分段B+樹的效果遠好于二叉樹的數據劃分,其大大減少了查詢特定主鍵所需的IO操作。
除此以外,B+樹能夠提供髙效的范圍掃描功能,這得益于它的葉節點相互連接并且按主鍵有序,掃描時避免了耗時的遍歷樹操作。這也是B+樹被關系型數據庫用作索引的原因之一。
如果要進行一次范圍査詢,則可能需要讀取多個在磁盤上不連續甚至可能相隔很遠的葉節點頁表。這也是為什么我們在大部分基于B+樹的設計中都能找到一組被稱為OPTIMIZE TABLE命令的原因,B+樹這種數據組織方式只是簡單地按順序把表重寫,從而使表的范圍查詢變成了磁盤的多段連續讀取。
8.1.2 LSM樹
LSM樹(log-structured merge-tree)。則按另一種方式組織數據。輸入數據首先被存儲在日志文件,這些文件內的數據完全有序。當有日志文件被修改時,對應的更新會被先保存在內存中來加速查詢。
當系統經歷過許多次數據修改,且內存空間被逐漸被占滿后,LSM樹會把有序的“鍵記錄”對寫到磁盤中,同時創建一個新的數據存儲文件。此時,因為最近的修改都被持久化了,內存中保存的最近更新就可以被丟棄了。
存儲文件的組織與B樹相似,不過其為磁盤順序讀取做了優化,所有節點都是滿的并按頁存儲。修改數據文件的操作通過滾動合并完成,也就是說,系統將現有的頁與內存刷寫數據混合在一起進行管理,直到數據塊達到它的容量。
多次數據刷寫之后會創建許多數據存儲文件,后臺線程就會自動將小文件聚合成大文件,這樣磁盤查找就會被限制在少數幾個數據存儲文件中。磁盤上的樹結構也可以拆分成獨立的小單元,這樣更新就可以被分散到多個數據存儲文件中。所有的數據存儲文件都按鍵排序,所以沒有必要在存儲文件中為新的鍵預留位置。
查詢時先查找內存中的存儲,然后再查找磁盤上的文件。這樣在客戶端看來數據存儲文件的位置是透明的。
刪除是一種特殊的更改,當刪除標記被存儲之后,査找會跳過這些刪除過的鍵。當頁被重寫時,有刪除標記的鍵會被丟棄。
比較B+樹和LSM樹的意義在于理解它們的相對優勢和不足。在沒有太多的修改時,B+樹表現得很好,因為這些修改要求執行高代價的優化操作以保證查詢能在有限時間內完成。在任意位置添加數據的規模越大、速度越快,這些頁成為碎片的速度就越快。最后,用戶寫入的速度可能比優化后重寫文件的處理速度更快。由于更新和刪除以磁盤尋道的速率完成,這就強制用戶就范于磁盤提供的較差的性能指標。
LSM樹以磁盤傳輸速率工作并能較好地擴展以處理大量的數據。它們使用日志文件和內存存儲來將隨機寫轉換成順序寫,因此也能保證穩定的數據插入速率。由于讀和寫獨立,因此在這兩種操作之間沒有沖突。
由于存儲數據的布局較優,查詢一個鍵需要的磁盤尋道次數在一個可預測的范圍內,并且讀取與該鍵連續的任意數量的記錄都不會引發任何額外的磁盤尋道。一般來說,基于LSM樹的系統強調的是成本透明:假如有5個存儲文件,一個訪問需要最多5次磁盤尋道。反觀關系型數據庫,即使在存在索引的情況下,它也沒有辦法確定一次查詢需要的磁盤尋道次數。
8.2 存儲
8.2.1 概覽
從這張圖可以看出HBase主要處理兩種文件:一種是預寫日志(Write-Ahead Log WAL),另一種是實際的數據文件。這兩種文件主要由 HRegionServer管理。
一個基本的流程是客戶端首先聯系 ZooKeeper子集群(quorum)(一個由 ZooKeeper節點組成的單獨集群)査找行鍵。上述過程是通過ZooKeeper獲取含有-ROOT-的region服務器名(主機名)來完成的。通過含有-ROOT-的 region服務器可以查詢到含有.META.表中對應的 region服務器名,其中包含請求的行鍵信息。這兩處的主要內容都被緩存下來了,并且都只查詢一次。最終,通過查詢META服務器來獲取客戶端查詢的行鍵數據所在region的服務器名。
一旦知道了數據的實際位置,即 region的位置,HBase會緩存這次查詢的信息,同時直接聯系管理實際數據的HRegionServer。所以,之后客戶端可以通過緩存信息很好地定位所需的數據位置,而不用再次查找META表。
啟動 HBase時,MAster負責將所有region分配到每個HRegionServer上,
其中也包括特別的-ROOT-和.META.表。
HRegionServer負責打開region,并創建對應的HRegion實例。當HRegion被打開后它會為每個表的HColumnFamily創建一個Store實例,這些列族是用戶之前創建表時定義的。每個Strore實例包含一個或多個StoreFile實例,它們是實際數據存儲文件HFile的輕量級封裝。每個Store還有其對應的一個 MemStore,一個 HRegionServer分享一個HLog實例。
8.2.2 寫路徑
當用戶向HRegionServer發起HTable.put(Put)請求時,其會將請求交給對應的HRegion實例來處理:
8.2.3 文件
1. 根級文件
第一組文件是被HIog實例管理的WAL文件,這些日志文件被創建在HBase的根目錄下一個名為.logs的目錄中。對于每個 HRegionServer,日志目錄中都包含一個對應的子目錄。在每個子目錄中有多個Hlog文件(因為日志滾動)。一個 region服務器的所有region共享同一組HLog文件。
當所有包含的修改都被持久化到存儲文件中,從而不再需要日志文件時,它們會被放到HBase根目錄下的.oldlogs目錄中。當條件滿足配置上的閾值會觸發日志的滾動。在10分鐘(默認情況下)后,舊的日志文件將被master刪除。
2. 表級文件
在HBase中,每張表都有自己的目錄,其位于文件系統中HBase根目錄下。每張表目錄包括一個名為.tableinfo的頂層文件,該文件存儲表對應序列化后的理HTableDescriptor。其中包括表和列族的定義。.tmp目錄中包含一些臨時數據,例如,當更新.tableinfo文件時生成的臨時數據就會被存放到該目錄中。
3. region級文件
在每張表的目錄里面,表模式中每個列族都有一個單獨的目錄。目錄的名字是一部分region名字的MD5散列值。例如,下面的內容是在點擊master網頁界面中用戶表區域的testtable鏈接時得到的。
testtable, row-500,1309812163930.dgffc3a5cd016ae58e23d7a6cb937949
MD5散列值是d9ffc3a5cd016ae58e23d7a6cb937949,它是通過編碼region名字得到的,例如, testtable,row-500,1309812163930.,末尾的點是這個 region名字的一部分。
散列能保證目錄名稱不違背文件系統的命名規則、:它們不能包含任何特殊字符。例如,用來劃分路徑的斜線(“/”)。 region文件的總體結構是:
/<hbase-root-dir>/<tablename>/<encoded-regionname>/<column-family>/<filename>
region目錄中也有一個.regioninfo文件,這個文件包含了對應region的 HRegionInfo實例序列化后的信息。
可選的.tmp目錄是按需求創建的,它被用來存放臨時文件,例如,一次合并的重寫文件。一旦這個過程完成,這些臨時生成的文件通常會被移到region目錄中。在極少的情況下,用戶可能發現遺留的文件,這些文件將在region重新打開時被清理掉。
一旦region超過了配置中 egion大小的最大值,,region就需要拆分,其會創建一個對應的splits目錄,它被用來臨時存放兩個子region相關的數據。如果拆分過程成功(通常這個過程持續幾秒或更短時間),之后它們會被移動到表目錄中,并形成兩個新的region,每個region代表原始region的一半。
4. region拆分
當一個region里的存儲文件增長到大于配置的hbaseregion.max.filesize大小或者在列族層面配置的大小時,region會被一分為二。這個過程通常非常迅速,因為系統只是為新region(也稱作孩子)創建了兩個對應的文件,每個 region是原始region(稱作父親)的一半。
region服務器通過在父region中創建splits目錄來完成這個過程,接下來關閉該region,此后這個region不再接受任何請求。
5. 合并
存儲文件會被后臺的管理進程仔細地監控起來以確保它們處于控制之下。隨著memstore的刷寫會生成很多磁盤文件。如果文件的數目達到閾值,合并(compaction)過程將把它們合并成數量更少的體積更大的文件。這個過程持續到這些文件中最大的文件超過配置的最大存儲文件大小,此時會觸發一個region拆分。
壓縮合并有兩種,即minor和 major:
- minor合并負責重寫最后生成的幾個文件到個更大的文件中。
- major合并負責把所有文件壓縮成一個單獨的文件。
8.2.4 HFile格式
實際的存儲文件功能是由HFile類實現的,它被專門創建以達到一個目的:有效地存儲HBase的數據。
這些文件是可變長度的,唯一固定的塊是File Info塊和Trailer塊。如圖8-5所示,Trailer有指向其他塊的指針。它是在持久化數據到文件結束時寫入的,寫入后即確定其成為不可變的數據存儲文件。 Index塊記錄Data和Meta塊的偏移量。Data和Meta塊實際上都是可選的,但是考慮到HBase如何使用數據文件,在存儲文件中用戶幾乎總能找到Data塊。每個塊都包含一個magic頭部和一定數量的序列化的KeyValue實例。
在HDFS中,文件的默認塊大小是64MB,這個是HFile默認塊大小的1024倍。因此HBase存儲文件的塊與Hadoop的塊之間沒有匹配關系。事實上,這兩種塊類型之間根本沒有相關性。 HBase把它的文件透明地存儲到文件系統中,而HDFS也使用塊來切分文件僅僅是一個巧合,并且HDFS不知道 HBase存儲的是什么,它只能看到二進制文件。圖8-6展示了HFile的內容怎樣在整個HDFS塊中進行分布。
8.2.5 KeyValue格式
本質上,HFile中的每個KeyValue都是一個低級的字節數組,它允許零復制訪問數據。圖8-7顯示了所包含數據的布局。
該結構以兩個分別表示鍵長度(Key Length)和值長度(Value Length)的定長數字開始。有了這個信息,用戶就可以在數據中跳躍,例如,可以忽略鍵直接訪問值。
上面的例子中,平均鍵比平均值大的原因可以歸結為鍵中包含的數據項:它包含了指定單元的全維度內容。鍵包含了行鍵、列族名和列限定符等。相對于一個較小的有效負載,這將導致相當巨大的開銷。如果用戶處理的值較小,那么應當保持鍵盡量小。選擇一個短的行和列鍵(列族名是一個單字節,同時列限定符也一樣短)來保證鍵值比率合適。
另一方面,壓縮有助于緩解這一問題,因為它著眼于有限的數據窗口,并且其中所有重復的數據都能夠被有效地壓縮。存儲文件中所有的KeyValue都被有序地存儲,這樣有助于把類似的鍵(如果用戶使用了版本,那么相似的值也會這樣)放在一起。
8.3 WAL
region服務器會將數據保存到內存中,直到積攢足夠多的數據再將其刷寫到硬盤上,這樣可以避免創建很多小文件。存儲在內存中的數據是不穩定的,例如,在服務器斷電的情況下數據就可能會丟失。
一個比較常見的解決這個問題的方法是預寫日志(WAL):每次更新(也叫做“編輯”)都會寫入日志,只有寫入成功才會通知客戶端操作成功,然后服務器可以按需自由地批量處理或聚合內存中的數據。
8.3.1 概述
當災難發生的時候,WAL就是所需的生命線。類似于MySQL的binary log,WAL存儲了對數據的所有更改。這也就意味著如果將記錄寫入到WAL失敗時,整個操作也會被認為是失敗的。
8.2.1節展示了WAL是怎樣和 HBase的架構結合在一起的。因為它被同一個 region服務器的所有region共享,所以對于每一次修改它就像一個日志中心一樣。圖8-8展示了編輯流是怎樣在memstore和WAL之間分流的。
處理過程如下:
- 首先客戶端啟動一個操作來修改數據。例如,可以對put()、 delete()和
increment()進行調用。每一個修改都封裝到一個KeyValue對象實例中,并通過RPC調用發送出去。這些調用(理想情況下)成批地發送給含有匹配 region的HRegionServer - 一旦KeyValue實例到達,它們會被發送到管理相應行的HRegion實例。數據被寫入到WAL,然后被放入到實際擁有記錄的存儲文件的memstore中。實質上,這就是 HBase大體的寫路徑。
- 最后,當memstore達到一定的大小或是經歷一個特定的時間之后,數據就會異步地連續寫入到文件系統中。在寫入的過程中,數據以一種不穩定的狀態存放在內存中、,即使在服務器完全崩潰的情況下,WAL也能夠保證數據不會丟失,因為實際的日志存儲在HDFS上。其他服務器可以打開日志文件然后回放這些修改—恢復操作并不在這些崩潰的物理服務器上進行。
8.3.2 HLog類
HLog類的核心功能是 append()方法。注意,為了提高性能,在Put、 Delete和Increment中可以使用一個額外的參數集合:setWriteToWAL(false)。如果用戶在設置時調用這個方法,例如,用戶在設置一個Put實例時調用該方法會導致向WAL寫入數據的過程停止。這也是為什么圖8-8中使用虛線創建的向下的箭頭來表示可選步驟。
HLog的另一個特性是追蹤修改,這個特性可以通過使用序列號來實現。它在內部使用一個進程安全的atomic long,且從0開始或從保存在文件系統中的最后一個所知的數字開始:當region打開它的存儲文件時,它讀取存儲在每一個HFile中meta域中最大的序列號,并且如果這個序列號大于之前記錄的序列號,它就會把HLog的序列號設定為這個值。所以在打開所有存儲文件的結尾后,HLog就會被初始化以反映存儲在哪里結束以及從哪里繼續存儲。
8.3.3 HLogKey類
WAL當前使用的是Hadoop的Sequencefile,這種文件格式按照鍵/值集合的方式存儲記錄。對WAL來說,值僅僅是客戶端發送的修改請求。Key被 HLogKey實例代表:由于KeyValue僅僅代表行鍵、列族、列限定詞、時間戳、類型以及值,所以要有個地方來存儲 KeyValue的歸屬,即region和表名,這個信息存儲在HLogKey中。 HLogKey還存儲了上面所提到的序列號。每一條記錄的數字是遞增的,以保持一個連續的編輯序列。
它還記錄了寫入時間,這是一個表示修改是什么時候被寫入到日志的時間戳。最后,這個類存儲了多個集群之間進行復制所需要的集群ID(cluster ID)。
8.3.4 WALEdit類
客戶端發送的每一個修改都會被封裝到一個 WALEdit實例。它通過日志級別來管理原子性。假設更新了一行中的10列,每一列或每一個單元格都是一個單獨的KeyValue實例,如果服務器將它們中的5個寫入到WAL后就失敗了,用戶就會得到一半修改內容被持久化了的行。
這可以通過將包含多個單元格的,且所有被認為是原子的更新都寫入到一個 WALEdit實例中來解決。這一組的修改都會在一次操作中被寫入,以保證日志的一致性。
8.3.5 LogSyncer類
表的描述符允許用戶設置一個叫做延遲日志刷寫(deferred log flush)的標志。
用戶將deferred log flush標志位設置為true會導致修改被緩存在region服務器中,然后在服務器上LogSyncer類會作為一個線程運行,負責在非常短的時間間隔內調用sync()方法。默認的時間間隔為1秒,可以通過hbase. regionserver.optionallogflushinterval屬性來設置。
注意這只作用于用戶表,所有的目錄表會一直保持同步。
8.3.6 LogRoller類
日志的寫入是有大小限制的。LogRoller類會作為一個后臺線程運行,并且在特定的時間間隔內滾動日志。這可以通過hbase,.regionserver, logroll. period屬性來控制,默認值是1小時。
每60分鐘舊的日志文件被關閉,然后開始使用新的日志文件。經過一段時間,系統會積攢一系列數量不斷遞增的日志文件,這些文件也需要維護。 LogRoller會調用HLog.rollWriter()方法來做上面所說的滾動當前日志文件的工作,接著HLog.rollWriter()會調用HLog.cleanOldLogs()。
HLog. cleanOldLogs()會檢查寫入到存儲文件中的最大序列號是多少,這是因為到這個序列號為止(小于或等于這個序列號)的所有修改都已經被保存了。然后它會檢查是不是有日志文件的序列號都小于這個數字。如果是的話,它就會將這些文件移動到.oldlogs文件夾中,留下其余的日志。
8.3.7 回放
master和region服務器需要配合起來精確地處理日志文件,特別是需要從服務器失效中恢復的時候。WAL用來保持數據更新的安全,而回放則是一個使得系統恢復到一致性狀態的更加復雜的過程。
1. 單日志
為什么不分開將每個region的所有數據更改都寫入到一個單獨的日志文件中去呢?下面是引自BigTable論文的相關內容:
如果我們將不同表的日志提交到不同日志文件中去的話,就需要向GFS并發地寫入大量文件。以上操作依賴于每個GFS服務器文件系統的底層實現,這些寫入會導致大量的硬盤尋道來向不同的物理日志文件中寫入數據。
由于相同的原因,HBase也遵循這個原則:同時寫入太多的文件,且需要保留滾動的日志會影響系統的擴展性。這種設計最終是由底層文件系統決定的。雖然在 HBase中可以替換底層文件系統,但是通常情況下安裝還是會選用HDFS。
只要遇到服務器崩潰,系統就需要拆分日志,即把日志分成合適的片,這
些在下一節有相應的描述。所有的數據更改的日志都混在一個日志文件中,并且沒有任何索引。正是由于這個原因,master不可能立即把一個崩潰的服務器上的region部署到其他服務器上,它需要等待對應region的日志被拆分出來。
2. 日志拆分
有兩種日志文件需要被回放的情況:集群啟動時或服務失效時。當 master啟動的時候——這也包括備用的master接管系統的時候——它會檢查文件系統中HBase根目錄.logs文件夾下是不是有日志文件,以及這些日志有沒有分配的region服務器。日志的名字不僅包含服務器的名字,還包含服務器的啟動碼(start code)。這個數字會在每次region服務器重啟的時候重置。 master可以通過這個數字來檢查日志是否被遺棄了。
master還需要負責監控服務器如何使用ZooKeeper。當master檢測到一個服務器失效時,它就會在重新分配region到新的服務器前立即啟動一個進程來恢復日志文件。
在日志中的數據改動被回放之前,日志需要被單獨放在每個region對應的單獨的日志文件中。這個過程叫做日志拆分(log splitling):讀取混在一起的日志,并且所有的條目都按照它所歸屬的 egion來分組。
日志拆分的實質操作過程幾乎在每一個 HBase版本中都不太一樣:早期版本會直接在master上通過一個線程來讀取文件。這個后來又提升為至少不同 region對應的修改是通過多線程的方式來重新執行。在0.920版本中,終于引入了分布式日志拆分(distributed log splitting)的概念,切分日志的實際工作從master轉移到了region服務器上。
最新的分布式模式使用ZooKeeper來將每一個被丟棄的日志文件分發給一個
region服務器。它們通過監測ZooKeeper來發現需要執行的工作,一旦 master指出某個日志是可以被處理的,那么它們會競爭這個任務。獲勝的 region服務器就會在一個線程(為了不使已經負載很重的region服務器過載)中讀取并且拆分這個日志文件。
一旦日志文件被成功拆分,則每個region對應的文件就會被移動到實際的 region目錄。然后region就可以使用對應的日志來恢復數據了。這也就是為什么拆分需要阻塞打開region,因為它需要首先提供掛起的修改來回放。
3. 數據恢復
當集群啟動,或region從一個region服務器移動到另一個region服務器時,region都會被打開,且此時region會首先檢查recovered.edits目錄是否存在。如果該目錄存在,它就會打開該目錄中的文件,并開始讀取文件所包含的數據更改記錄。由于文件是按照含序列ID的文件名排序的,region便可以按照序列ID的順序來恢復數據。
任何序列ID小于或者等于保存在硬盤中存儲文件序列ID的更改記錄都會被忽略,因為這些記錄之前的數據已經被刷寫了。其他數據更新都會被添加到對應region的memstore中來恢復之前的數據狀態。最后,一次強制的memstore刷寫會將當前數據寫入到硬盤中。
一旦recovered. edits文件夾中的文件都被處理完,且其中的數據更改也都被寫入到硬盤后,該文件夾就會被刪除。
8.3.8 持久性
略~
8.4 讀路徑
由于所有的存儲文件都是不可變的,從這些文件中刪除一個特定的值是做不到的,通過重寫存儲文件將已經被刪除的單元格移除也是毫無意義的。墓碑標記就是用于此類情況的,它標記著“已刪除”信息,這個標記可以是單獨一個單元格、多個單元格或整行。
假設用戶今天在給定的一行中寫入了一列數據,然后在未來的幾天里不停地在其他幾行中添加數據,然后再在之前給定行的其他列中寫入數據。需要考慮的問題是,假設之前添加的列數據已經作為KeyValue在硬盤存儲了一段時間,由于新寫入的列數據會存儲在memstore里或者也被刷寫到硬盤中,那么邏輯上的一整行數據到底存儲在了哪里呢?
換句話說,當使用Shell對那一行執行一個ger命令時,系統怎么知道該返回什么?作為客戶端,我們希望兩列都被返回——就好像它們被存儲在同一個實體中一樣。但是實際上數據存儲在分離的KeyValue實例中,橫跨任意數目個存儲文件。
如果刪除了最初的列值,然后再次執行get命令時,我們期望這個值已經被刪除,然而實際上它仍然存在于某處,只是墓碑標記指出用戶已經刪除了它。但是標記可能存儲在距離所需刪除數據很遠的地方。8.1節詳細解釋了這個方式背后的架構。
HBase通過使用QueryMatcher和ColumnTracker來解決這個問題:其中一個需要精確地匹配用戶要取出的列,另一個則需要包含所有的列。它們都可以設定最大匹配的版本數。它們會跟蹤要被包含列到最終結果中的內容。
為什么Get都是Scan
這時該介紹一下HBase的架構了。 HBase中沒有可以使我們直接訪問特定行或列的索引文件。HFile中最小的單元是塊,并且為了找到所要求的數據,RegionServer代碼和它底層實現的store實例必須載入整個可能存儲著所需數據的塊并且掃描這個塊。以上就是Scan做的事情。
也就是說,一次Get就僅僅對單獨一行進行掃描。用戶可以創建一次Scan,并且將開始行設定為你尋找的那行,且將結束行設定為start row+1。
在讀取所有存儲文件來查找匹配的條目之前,需要有一個快速的排除檢查階段:使用時間戳以及可選的布隆過濾器來跳過那些絕對不包含所需 KeyValue的文件。然后,掃描剩下的存儲文件以及memstore來尋找匹配的鍵。
圖8-10將一個邏輯行表示為一組KeyValue,其中一些在相同的存儲文件中,一些在另外一些文件中,并能夠橫跨多個列族。一個存儲文件和memstore在基于時間戳和布隆過濾器的排除過程中被跳過。最后一個存儲文件中的刪除標記被用來屏蔽條目,但是它們仍然屬于同一行數據。掃描器——被表示為存儲文件附近的箭頭——處于文件中的第一個符合的條目或是緊挨著所要求的行,后者是因為這個存儲文件中沒有直接匹配的條目。
8.5 region查找
-RQOT-表用來查詢所有.META.表中region的位置。 HBase的設計中只有一個root region,即root region從不進行拆分,從而保證類似于B+樹結構的三層查找結構:第一層是ZooKeeper中包含root region位置信息的節點,第二層是從-RQOT-表中查找對應meta region的位置,第三層是從.META.表中查找用戶表對應region的位置。
雖然客戶端緩存了region的地址,但是初始化需求時需要重新查找region,例如,緩存過期了,并發生了 region的拆分、合并或移動。客戶端厙函數使用遞歸查找的方式從目錄表中重新定位當前region的位置。它會從對應的meta region查找對應行鍵的地址。如果對應的meta region地址無效,它就向root表詢問當前對應的meta表的位置。最后,如果連root表的地址也失效了,它會向 ZooKeeper節點查詢root表的新地址。在最壞的情況下,客戶端需要6次網絡往返請求來定位一個用戶 region。
圖8-11展示了先通過meta表,最終通過root表來確定一個用戶region位置的過程。如果緩存不為空,但緩存的用戶region、meta region和root region的位置都失效了,則需要額外的3次查詢,即總共需要6次查詢來完成這次定位。
8.6 region的生命周期
略~
8.7 ZooKeeper
略~
8.8 復制
HBase復制中最基本的架構模式是“主推送”(master-push),因為每個 region服務器都有自己的WAL(或HLog),所以及很容易保存現在正在復制的位置,其類似于其他眾所周知的解決方案,例如,MySQL的主從復制只使用二進制日志來跟蹤修改。一個主集群可以將數據復制到任意數目的從集群,每個region服務器都會參與復制自己的修改。
復制是異步進行的,意味著集群可以是地理上彼此遠離的,它們之間的連接可以在某些時間斷開,在主集群上的修改不能馬上在從集群上進行同步(最終一致性)。圖8-12展示了復制的工作流程和架構。
每個region服務器從它需要的最老的日志開始復制,同時在ZooKeeper中保存當前恢復的位置來簡化錯誤恢復。每個從集群恢復的位置可能不同,但它們處理的HLog隊列內容是相同的。
8.8.1 Log Edit的生命周期
略~
8.8.2 內部機制
略~
總結
以上是生活随笔為你收集整理的《HBase权威指南》读书笔记(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无法打开“XXXX”,因为Apple无法
- 下一篇: Educational Codeforc