Hbase Architecture[下]

概述:

  1. Read Path
  2. Region查找
    2.1 Region生命週期
  3. ZooKeeper
  4. Replication
    4.1 Life of a Log Edit
    4.1.1 正常處理流程
    4.1.2 Non-responding Slave Clusters
    4.2 Internals
    4.2.1 選擇複製到目標Region Servers
    4.2.2 日誌追蹤
    4.2.3 讀、過濾及發送Edits
    4.2.4 日誌清理
    4.2.5 Region Server 故障恢復
    原文鏈接

1. Read Path

HBase中的每個column family可能有多個文件,文件中包含實際的cells或者是KeyValue實例。當memstore中積累的更新被flush到磁盤上時這些文件就會創建出來。負責compaction的後臺線程會通過將小文件合併成更大的文件來將文件數控制在一定水平上。Major compaction最終會將所有的文件集合壓縮成一個,之後隨着flush的進行,小文件又會出現。

因爲所有的存儲文件都是不可變的,所以就沒法直接將一個值從它們裏面刪除,也沒法對某個值進行覆蓋。而只能通過寫入一個墓碑式的標記,來代表某個cell或者某幾個cell或者是整行都被刪除了。

假設今天你在給定的一行裏寫了一個列,之後你一直不斷的添加數據,那麼你可能會爲該行寫入另一個列。問題是,假設最初的列值已經被持久化到了磁盤中,而新寫入的列還在memstore中,或者已經被flush到了磁盤,那該行到底算存放到哪呢?換句話說,當你對該行執行一個get命令時,系統怎麼知道該返回什麼內容?作爲一個客戶端,你可能希望返回所有的列—看起來它們好像就是一個實體一樣。但是實際的數據是存儲在獨立的KeyValue實例中的,而且可能跨越任意數目的存儲文件。

如果你刪除了最初的那個列值,然後再執行get操作,你希望該值已經不存在了,雖然實際上它還存在於某處,但是墓碑式的標記表明你已經把它刪除了。但是該標記很有可能與你要刪除的值是分開存儲的。關於該架構更細節的內容參見the section called “Seek vs. Transfer”。

該問題是通過使用QueryMatcher以及一個ColumnTracker解決的。在讀取所有的存儲文件以找到一個匹配的記錄之前,可能會有一個快速的排除檢查,可以使用時間戳或者Bloom filter來跳過那些肯定不包含該記錄的存儲文件。然後,對剩餘的存儲文件進行掃描以找到匹配該key的記錄。

爲何Gets即Scans

在HBase之前的版本中,Get方法的確是單獨實現的。最近的版本進行了改變,目前它內部已經和Scan API使用相同的源代碼。

你可能會很奇怪,按理來說一個簡單的Get應該比Scan快的。把它們區分對待,更容易針對Get進行某些優化。實際上這是由HBase本身架構導致的,內部沒有任何的索引文件來支持對於某個特定的行或列的直接訪問。最小的訪問單元就是HFile中的一個block,爲了找到被請求的數據,RegionServer代碼和它的底層Store實例必須load那些可能包含該數據的blocks然後進行掃描。實際上這就是Scan的操作過程。換句話說,Get本質上就是對單個行的Scan,就是一個從start row到start row+1的scan。

Scan是通過RegionScanner類實現的,它會每個Store實例(每個代表一個column family)執行StoreScanner檢索,如果讀操作沒有包含某個column family,那麼它的Store實例就會被略過。

StoreScanner會合並它所包含的存儲文件和memstore。同時這也是根據Bloomfilter或者時間戳進行排除性檢查的時候,然後你可以跳過那些不需要的存儲文件。參見the section called “Key Design”瞭解排除性檢查的細節,以及如何利用它。

同時也是由StoreScanner持有QueryMatcher(這裏是ScanQueryMatcher類)。它會記錄下那些包含在最終結果中的KeyValue。

RegionScanner內部會使用一個KeyValueHeap類來按照時間戳順序安排所有的Store scanners。StoreScanner也會採用相同的方式來對存儲文件進行排序。這就保證了用戶可以按照正確的順序進行KeyValue的讀取(比如根據時間戳的降序)。

在store scanners被打開時,它們會將自己定位到請求的row key處。準備進行數據讀取。

Figure 8.10. Rows are stored and scanned across different stores, on-disk or in-memory

HBase Architecture(譯):下 - 星星 - 銀河裏的星星

對於一個get()調用,所有的服務器需要做的就是調用RegionScanner的next()。該調用內部會讀取組成結果的所有內容。包括所有請求的版本,假設某列有三個版本,同時用戶請求檢索它們中所有的。這三個KeyValue可能分佈在磁盤或內存中的存儲文件。Next()調用會從所有的存儲文件中讀取直到讀到下一行,或者直到讀到足夠的版本。

與此同時,它也會記錄那些刪除標記。當它掃描當前行的KeyValue時,可能會碰到這些刪除標記,那些時間戳小於等於該刪除標記的記錄都會被認爲是已經清除掉了。

圖中展示了一個由一系列KeyValue組成的邏輯行,某些存儲在相同的存儲文件中,某些在其他文件上,包含了多個column family。由於時間戳或者Bloom filter的排除過程,某些存儲文件和memstore可能會被跳過。最後一個存儲文件中的刪除標記可能會遮蔽掉所有的記錄,但是它們仍然是同一行的一部分。這些scanners—實際上可以用一系列指向存儲文件的箭頭表示—要麼指向文件中的第一個匹配點,要麼是緊挨着所請求的key的那個點(如果沒有直接匹配的點的話)。

在執行next調用時,只有那些具有匹配點的scanners纔會被考慮。內部循環會從第一個存儲文件到最後一個存儲文件,按照時間地降序一個挨一個地讀取其中的KeyValue,直到超出當前請求的key。

對於scan操作,則是通過在ResultScanner上不斷的調用next(),直到碰到表的結束行或者爲當前的batch讀取了足夠多的行時。

最終的結果是一個匹配了給定的get或者scan操作的KeyValue的列表。它會被髮送給客戶端,客戶端就可以使用API函數來訪問裏面的列。

2. Region查找

爲了讓客戶端能夠找到持有特定的row key range的region server,HBase提供了兩個特殊的元數據表:-ROOT-和.META.。

-ROOT-表用於保存.META.表的所有regions的信息。HBase認爲只有一個root region,同時它永不會被split,這樣就可以保證一個三層的類B+樹查找模式:第一層是存儲在ZooKeeper上的一個保存了root 表的region信息的節點,換句話說就是保存了root region的那個region server的名稱。第二層需要到-ROOT-表中查找匹配的meta region,然後第三層就是到.META.表中檢索用戶表的region信息。

元數據表中的row key由每個region的表名,起始行,及一個ID(通常使用當前時間,單位是毫秒)。從HBase 0.90.0開始,這些key可能會有一個額外的與之關聯的hash值。目前只是用於用戶表中。

注:Bigtable論文指出,在.META.表的region大小限制在128MB的情況下,它可以尋址2^34個regions,如果按每個region 128MB大小算,就是2^61字節大小。因爲region大小可以增加而不會影響到定位模式,因此根據需要這個值還可以增大。

儘管客戶端會緩存region位置信息,但是客戶端在首次查詢時都需要發送請求來查找特定row key或者一個region也可能會被split,merge或者移動,這樣cache可能會無效。客戶端庫採用一種遞歸的方式逐層向上地找到當前的信息。它會詢問與給定的row key匹配的.META.表region所屬的region server地址。如果信息是無效的,它就退回到上層詢問root表對應的.META. region的位置。最後,如果也失敗了,它就需要讀取Zookeeper節點以找到root表region的位置。

最壞情況下,將會需要6次網絡傳輸才能找到用戶region,因爲無效記錄只有當查找失敗時才能發現出來,當然系統假設這種情況並不經常發生。在緩衝爲空的情況下,客戶端需要三次網絡傳輸來完成緩存更新。一種降低這種網絡傳輸次數的方法是對位置信息進行預取,提前更新客戶端緩存。具體細節見the section called “Miscellaneous Features”。

Figure 8.11. Starting with an empty cache, the client has to do three lookups.

HBase Architecture(譯):下 - 星星 - 銀河裏的星星

一旦用戶表region已知之後,客戶端就可以直接訪問而不需要進一步的查找。圖中對查找進行了標號,同時假設緩存是空的。

2.1. Region生命週期

Region的狀態會被master追蹤,通過使用AssignmentManager類。它會記下region從offline狀態開始的整個生命週期。表8.1列出了一個region的所有可能狀態。

Table 8.1. Possible states of a region

State

Description

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.

狀態間的轉換可能是由master引起,也可能是由持有它的那個region server引起。比如master可能將region分配給某個server,之後它會由該server打開。另一方面,region server可能會啓動split過程,這會觸發region打開和關閉事件。

由於這些事件本身的分佈式屬性,服務器使用ZooKeeper在一個專門的znode中記錄各種狀態。

3. ZooKeeper

從0.20.x開始,HBase使用ZooKeeper作爲它的分佈式協調服務。包括region servers的追蹤,root region的位置及其他一些方面。0.90.x版引入了新的master實現,與ZooKeeper有了更緊密的集成。它使得HBase可以去除掉master和region servers之間發送的心跳信息。這些現在都通過ZooKeeper完成了,當其中的某一部分發生變化時就會進行通知,而之前是通過固定的週期性檢查完成。

HBase會在它的根節點下創建一系列的znodes。根節點默認是”/hbase”,可以通過zookeeper.znode.parent進行配置。下面是所包含的znodes節點列表及其功用:

注:下面的例子使用了ZooKeeper命令行接口(簡稱CLI)來運行這些命令。可以通過如下命令啓動CLI:

ZK_HOME/bin/zkCli.sh -server

/hbase/hbaseid

包含了集羣ID,跟存儲在HDFS上的
hbase.id
文件中的一致. 如下:

[zk: localhost(CONNECTED) 1]
get /hbase/hbaseid
e627e130-0ae2-448d-8bb5-117a8af06e97

/hbase/master

包含了服務器名稱, (具體參見the section called “Cluster Status Information” ). 如下:

[zk: localhost(CONNECTED) 2]
get /hbase/master
foo.internal,60000,1309859972983

/hbase/replication

包含了replication的細節信息。相關細節參見 the section called “Internals”。

/hbase/root-region-server

包含了持有
-ROOT-
regions 的region server的服務器名稱。在region查找過程中會用到它 (見 the section called “Region Lookups”). 如下:

[zk: localhost(CONNECTED) 3]
get /hbase/root-region-server
rs1.internal,60000,1309859972983

/hbase/rs

作爲所有region servers的根節點,會記錄它們是何時啓動。用來追蹤服務器的失敗。每個內部的znode節點是臨時性的,以它所代表的region server的服務器名稱爲名。比如:

[zk: localhost(CONNECTED) 4]
ls /hbase/rs[rs1.internal,60000,1309859972983,rs2.internal,60000,1309859345233]
/hbase/shutdown

該節點用於追蹤集羣狀態。包含集羣啓動時間,當集羣關閉時其內容爲空。比如:

[zk: localhost(CONNECTED) 5]
get /hbase/shutdown Tue Jul 05 11:59:33 CEST 2011
/hbase/splitlog

用於所有log splitting相關協調的parent znode, 細節詳見 the section called “Log Splitting” 。比如:

[zk: localhost(CONNECTED) 6]
ls /hbase/splitlog
[hdfs%3A%2F%2Flocalhost%2Fhbase%2F.logs%2Ffoo.internal%2C60020%2C \1309850971208%2Ffoo.internal%252C60020%252C1309850971208.1309851636647,hdfs%3A%2F%2Flocalhost%2Fhbase%2F.logs%2Ffoo.internal%2C60020%2C \1309850971208%2Ffoo.internal%252C60020%252C1309850971208.1309851641956,…hdfs%3A%2F%2Flocalhost%2Fhbase%2F.logs%2Ffoo.internal%2C60020%2C \1309850971208%2Ffoo.internal%252C60020%252C1309850971208.1309851784396]
[zk: localhost(CONNECTED) 7]
get /hbase/splitlog/ \
\hdfs%3A%2F%2Flocalhost%2Fhbase%2F.logs%2Fmemcache1.internal%2C \

60020%2C1309850971208%2Fmemcache1.internal%252C60020%252C1309850971208. \

1309851784396 unassigned foo.internal,60000,1309851879862
[zk: localhost(CONNECTED) 8]
get /hbase/splitlog/ \

\hdfs%3A%2F%2Flocalhost%2Fhbase%2F.logs%2Fmemcache1.internal%2C \

60020%2C1309850971208%2Fmemcache1.internal%252C60020%252C1309850971208. \

1309851784396
owned foo.internal,60000,1309851879862
[zk: localhost(CONNECTED) 9]
ls /hbase/splitlog
[RESCAN0000293834, hdfs%3A%2F%2Flocalhost%2Fhbase%2F.logs%2Fmemcache1. \internal%2C60020%2C1309850971208%2Fmemcache1.internal%252C \60020%252C1309850971208.1309851681118, RESCAN0000293827, RESCAN0000293828, \RESCAN0000293829, RESCAN0000293838, RESCAN0000293837]

這些例子列出了很多東西:你可以看到一個未被分配的log是如何被split的,之後又如何被一個region server所擁有。”RESCAN”節點表示那些workers,比如萬一log split失敗後可能被用於進一步的工作的region server。

/hbase/table

當一個表被禁用時,它會被添加到該節點下. 表名就是新創建的znode的名稱,內容就是”DISABLED”。比如:

[zk: localhost(CONNECTED) 10]
ls /hbase/table
[testtable]
[zk: localhost(CONNECTED) 11]
get /hbase/table/testtable
DISABLED
/hbase/unassigned

該znode是由 AssignmentManager 用來追蹤整個集羣的region狀態的。它包含了那些未被打開或者處於過渡狀態的regions對應的znodes,zodes的名稱就是該region的hash。比如:

[zk: localhost(CONNECTED) 11]
ls /hbase/unassigned
[8438203023b8cbba347eb6fc118312a7]

4. Replication

HBase replication是在不同的HBase部署之間拷貝數據的一種方式。它可以作爲一種災難恢復解決方案,也可以用於提供HBase層的更高的可用性。同時它也能提供一些更實用的東西:比如,可以作爲從面向web的集羣中拷貝最新的更新內容到MapReduce集羣的簡單方式,然後利用MapReduce集羣對新老數據進行處理再自動地返回結果。

HBase replication採用的基本架構模式是:master-push;因爲每個region server都有自己的write-ahead-log(即WAL或HLog),這樣就很容易記錄下從上次複製之後又發生了什麼,非常類似於其他一些著名的解決方案,就像MySQL 的主從複製就只用了一個binary log來進行追蹤。一個master集羣可以向任意數目的slave集羣進行復制,同時每個region server會參與複製它本身所對應的一系列的修改。

Replication是異步進行的,這意味着參與的集羣可能在地理位置上相隔甚遠,它們之間的連接可以在某段時間內是斷開的,插入到master集羣中的那些行,在同一時間在slave集羣上不一定是可用的(最終一致性)。

在該設計中所採用的replication格式在原理上類似於MySQL的基於狀態的replication。在這裏,不是SQL語句,而是整個的WALEdits(由來自客戶端的put和delete操作的多個cell inserts組成)會被複制以維持原子性。

每個region server的HLogs是HBase replication的基礎,同時只要這些logs需要複製到其他的slave集羣上,它們就需要保存在HDFS上。每個RS會從它們需要複製的最老的log開始讀取,同時爲簡化故障恢復會將當前讀取位置保存到ZooKeeper上。對於不同的slave集羣來說,該位置可能是不同的。參與replication各集羣大小可能不是對稱的,同時master集羣會通過隨機化來儘量保證在slave集羣上的replication工作流的平衡。

Figure 8.12. Overview on the replication architecture

HBase Architecture(譯):下 - 星星 - 銀河裏的星星

4.1. Life of a Log Edit

下面的幾節裏會描述下來自客戶端的一個edit從與master集羣通信開始到到達另一個slave集羣的整個生命歷程。

4.1.1. 正常處理流程

客戶端會使用HBase API將Put,Delete和Increment發送給region server。Key values會被region server轉換爲一個WALEdit對象。該edit對象會被append到當前的WAL上,同時之後會被apply到它的MemStore中。

通過一個獨立的線程,將該edit對象從log中讀出然後只保留那些需要複製的KeyValues(也就是說只保留那些在family schema中只屬於GLOBAL作用域的family的成員,同時是非元數據也就是非.META和-ROOT-)。當buffer被填滿或者讀取者讀到文件末尾後,該buffer會被隨機發送到slave集羣上的某個region server上。region server順序地接受讀到的這些edits,同時將它們按照table放到不同的buffers中。一旦所有的edits讀取完畢,所有的buffer就會通過正常的HBase客戶端進行flush。

回頭再看master集羣的region server,當前複製到的WAL偏移位置會註冊到ZooKeeper上。

4.1.2. Non-responding Slave Clusters

Edit會以同樣的方式進行插入。在獨立的線程中,region server像正常處理過程那樣進行讀取,過濾以及對log edits進行緩存。假設現在所聯繫的那個slave集羣的region server不再響應RPC了,這樣master集羣的region server會進行休眠然後等待一個配置好的時間段後再進行重試。如果slave集羣的region server仍然沒有響應,master集羣的region server就會重新選擇一個要複製到的region server子集,然後會重新嘗試發送緩存的那些edits。

與此同時,WALs將會進行切換同時會被存儲在ZooKeeper的一個隊列中。那些被所屬的region server歸檔(歸檔過程基本上就是把一個日誌從它所屬的region server的目錄下移到一箇中央的logs歸檔目錄下)了的日誌會更新它們在複製線程的內存隊列中的路徑信息。

當slave集羣最終可用後,處理方式就又跟正常處理流程一致了。Master集羣的region server就又開始進行之前積壓的日誌的複製了。

4.2. Internals

本節會深入描述下replication的內部操作機制。

4.2.1. 選擇複製到的目標Region Servers

當一個master集羣的region server開始作爲某個slave集羣的複製源之後,它首先會通過給定的集羣key聯繫slave集羣的ZooKeeper。

該key由如下部分組成:

hbase.zookeeper.quorum

zookeeper.znode.parent

hbase.zookeeper.property.clientPort。

之後,它會掃描/hbase/rs目錄以找到所有可用的sinks(即那些可用接收用於複製的edits數據流的region servers)同時根據配置的比率(默認是10%)來選出它們中的一個子集。比如如果slave集羣有150臺機器,那麼將會有15臺選定爲master集羣的region server將要發送的edits的接受者。因爲複製過程中,master的所有region server都會進行,這樣這些slave集羣的region server的負載就可能會很高,同時該方法適用於各種大小的集羣。比如,一個具有10臺機器的master集羣向一個具有10%比率的5臺集羣的slave集羣進行復制。意味着master集羣的region servers每次都會隨機選擇一臺機器,這樣slave集羣的重疊和總的使用率還是很高的。

4.2.2. 日誌追蹤

每個master集羣的region server在replication znodes體系中都有自己的節點。同時節點下針對每個集羣節點還會有一個znode(如果有5個slave集羣,就會有5個znode創建出來),每個znode下又包含一個待處理的HLogs隊列。這些隊列是用來追蹤由該region server創建的HLogs的,這些隊列的大小可能有所不同。比如,如果某個slave集羣某段時間不可用,那麼這段時間的HLogs就不能被刪除,因此它們就得呆在隊列裏(而其他的可能已經處理過了)。具體例子可以參考:the section called “Region Server Failover”。

當一個source被實例化時,它會包含region server當前正在寫入的HLog。在log切換時,新的文件在可用之前就會被添加到每個slave集羣的znode的隊列中。這可以讓所有的sources在該HLog可以append edits之前就能夠知道一個新log已經存在了,但是該操作的開銷目前是很昂貴的。當replication線程無法從文件中讀出更多的記錄之後(因爲它已經讀到了最後一個block),就會將它從隊列中刪除,此時要求隊列中的還有其他文件存在{!還有其他文件存在就意味着這個文件是一個已經寫完的日誌文件,而不是正在寫入的那個}。這就意味着如果一個source已是最新狀態,同時複製進程已經到了region server正在寫入的那個log,那麼即使讀到了當前文件的”end”部分,也不能將它從隊列中刪除{!如果該文件正在被寫入,那麼即使讀到了末尾,也不能認爲它已經結束}。

當一個log被歸檔後(因爲它不再被使用或者是因爲插入速度超過了region flushing的速度導致當前log文件數超過了hbase.regionserver.maxlogs的限制),它會通知source線程該log的路徑已經發生改變。如果某個source已經處理完該log,會忽略該消息。如果它還在隊列中,該路徑會更新到相應的內存中。如果該log目前正在被複制,該變更會自動完成,讀取者不需要重新打開該被移動的文件。因爲文件的移動只是一個NameNode操作,如果讀取者當前正在讀取該log文件,它不會產生任何異常。

4.2.3. 讀,過濾及發送Edits

默認情況下,一個source會盡量地讀取日誌文件然後將日誌記錄儘快地發送給一個sink。但是首先它需要對log記錄進行過濾;只有那些具有GLOBAL作用域同時不屬於元數據表的KeyValues才能保留下來。第二個限制是,附加在每個slave集羣上所能複製的edits列表的大小限制,默認是64MB。這意味着一個具有三個slave集羣的master集羣的region server最多隻能使用192MB來存儲被複制的數據。

一旦緩存的edits大小達到上限或者讀取者讀到了log文件末尾,source線程將會停止讀取然後隨機選擇一個sink進行復制。它會對選定的集羣直接產生一個RPC調用,然後等待該方法返回。如果成功返回,source會判斷當前的文件是否已經讀完或者還是繼續從裏面讀。如果是前者,它會將它從znode的隊列中刪除。如果是後者,它會在該log的znode中註冊一個新的offset。如果PRC拋出了異常,該source在尋找另一個sink之前會重試十次。

4.2.4. 日誌清理

如果replication沒有開啓,master的logs清理線程將會使用用戶配置的TTL進行舊logs的刪除。當使用replication時,這樣是無法工作的,因爲被歸檔的log雖然超過了它們自己的TTL但是仍可能在隊列中。因此,需要修改默認行爲,在日誌超出它的TTL時,清理線程還要查看每個隊列看能否找到該log,如果找不到就可以將該log刪除。查找過程中它會緩存它找到的那些log,在下次log查找時,它會首先查看緩存。

4.2.5. Region Server故障恢復

只要region servers沒有出錯,ZooKeeper中的日誌記錄就不需要添加任何值。不幸的是,它們通常都會出錯,這樣我們就可以藉助ZooKeeper的高可用性和它的語義來幫助我們管理隊列的傳輸。

master集羣的所有region servers相互之間都有一個觀察者,當其中一個死掉時,其他的都能得到通知。如果某個死掉後,它們就會通過在死掉的region server的znode(該znode也包含它的隊列)內創建一個稱爲lock的znode來進行競爭性選舉。最終成功創建了該znode的region server會將所有的隊列傳輸到它自己的znode下(逐個傳輸因爲ZooKeeper並不支持rename操作)當傳輸完成後就會刪掉老的那些。恢復後的隊列的znodes將會在死掉的服務器的名稱後加上slave集羣的id來進行命名。

完成之後,master集羣的region server會對每個拷貝出的隊列創建一個新的source線程。它們中的每一個都會遵守read/filter/ship模式。主要的區別是這些隊列不會再有新數據因爲它們不再屬於它們的新region server,同時意味着當讀取者到達最後一個日誌的末尾時,隊列對應的znode就可以被刪除了,同時master集羣的region server將會關閉那個replication source。

比如,考慮一個具有3個region servers的master集羣,該集羣會向一個id爲2的單個slave集羣進行復制。下面的層次結構代表了znodes在某個時間點上的分佈。我們可以看到該region servers的znodes都包含一個具有一個隊列的peers znode。這些隊列的znodes的在HDFS上的實際文件名稱具有如下形式” address,port.timestamp”。

/hbase/replication/rs/ 1.1.1.1,60020,123456780/ peers/ 2/ 1.1.1.1,60020.1234 (Contains a position) 1.1.1.1,60020.1265 1.1.1.2,60020,123456790/ peers/ 2/ 1.1.1.2,60020.1214 (Contains a position) 1.1.1.2,60020.1248 1.1.1.2,60020.1312 1.1.1.3,60020, 123456630/ peers/ 2/ 1.1.1.3,60020.1280 (Contains a position)

現在我們假設1.1.1.2丟失了它的ZK會話,倖存者將會競爭以創建一個lock,最後1.1.1.3獲得了該鎖。然後它開始將所有隊列傳輸到它本地的peers znode,同時在原有的名稱上填上死掉的服務器的名稱。在1.1.1.3清理老的znodes之前,節點分佈如下:

/hbase/replication/rs/ 1.1.1.1,60020,123456780/ peers/ 2/ 1.1.1.1,60020.1234 (Contains a position) 1.1.1.1,60020.1265 1.1.1.2,60020,123456790/ lock peers/ 2/ 1.1.1.2,60020.1214 (Contains a position) 1.1.1.2,60020.1248 1.1.1.2,60020.1312 1.1.1.3,60020,123456630/ peers/ 2/ 1.1.1.3,60020.1280 (Contains a position) 2-1.1.1.2,60020,123456790/ 1.1.1.2,60020.1214 (Contains a position) 1.1.1.2,60020.1248 1.1.1.2,60020.1312

一段時間後,但在1.1.1.3結束來自1.1.1.2的最後一個HLog的複製之前,我們假設它也死掉了(而且某些之前創建的新logs還在正常隊列中)。最後一個region server會嘗試鎖住1.1.1.3的znode然後開始傳輸所有的隊列。新的節點分佈如下:

/hbase/replication/rs/ 1.1.1.1,60020,123456780/ peers/ 2/ 1.1.1.1,60020.1378 (Contains a position) 2-1.1.1.3,60020,123456630/ 1.1.1.3,60020.1325 (Contains a position) 1.1.1.3,60020.1401 2-1.1.1.2,60020,123456790-1.1.1.3,60020,123456630/ 1.1.1.2,60020.1312 (Contains a position) 1.1.1.3,60020,123456630/ lock peers/ 2/ 1.1.1.3,60020.1325 (Contains a position) 1.1.1.3,60020.1401 2-1.1.1.2,60020,123456790/ 1.1.1.2,60020.1312 (Contains a position)

Replication 目前還是一個處於實驗階段的feature。在將它應用到你的使用場景中時需要進行仔細地評估。

[83] See “B+ trees” on Wikipedia

[84] See LSM-Tree, O’Neil et al., 1996

[85] From “Open Source Search” by Doug Cutting, Dec. 05, 2005.

[86] See the JIRA issue HADOOP-3315 for details.

[87] For the term itself please read Write-Ahead Logging on Wikipedia.

[88] Subsequently they are referred to interchangeably as root table and meta table respectively, since for example
“-ROOT-”
is how the table is actually named in HBase and calling it root table is stating its purpose.

[89] See the online manual for details.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章