HBase Replication詳解

Replication:複製,指的是持續的將同一份數據拷貝到多個地方進行存儲,是各類存儲系統中常見而又重要的一個概念,能夠指數據庫中主庫和從庫的複製,也能夠指分佈式集羣中多個集羣之間的複製,還能夠指分佈式系統中多個副本之間的複製。它的難點在於數據一般是不斷變化的,須要持續的將變化也反映到多個數據拷貝上,並保證這些拷貝是徹底一致的。一般來講,數據複製到多個拷貝上有以下好處:html

  • 多個備份提升了數據的可靠性數據庫

  • 經過主從數據庫/主備集羣之間的複製,來分離OLTP和OLAP請求apache

  • 提升可用性,即便在單副本掛掉的狀況下,依然能夠有其餘副原本提供讀寫服務架構

  • 可擴展,經過增長副原本服務更多的讀寫請求負載均衡

  • 跨地域數據中心之間的複製,Client經過讀寫最近的數據中心來下降請求延遲異步


HBase中的Replication指的是主備集羣間的複製,用於將主集羣的寫入記錄複製到備集羣。HBase目前共支持3種Replication,分別是異步Replication,串行Replication,和同步Replication。async

異步Replication

若是想把HBase的Replication搞清楚,首先須要瞭解下HBase的架構。HBase集羣是由一組進程組成的,進程按角色分爲Master和RegionServer,其中Master負責DDL操做,好比建表、刪表,而RegionServer負責DML操做,好比數據的讀寫操做等。從數據視圖上講,HBase中的Table會按Range切分爲多個Region,而後由不一樣的RegionServer來負責對外提供服務。分佈式

RegionServer的內部則主要有BlockCache,MemStore和WAL等幾部分組成,須要注意的是每一個Region的每一個Column Family有本身獨享的MemStore,可是BlockCache和WAL則是多個Region共享的。WAL(Write-ahead logging)是數據庫中的經常使用技術,全部的修改在寫入數據庫以前都須要持久化到WAL中,從而確保了在出現故障的時候,能夠從WAL中回放出已經成功寫入的數據。ide

HBase中的Replication也是基於WAL的,其在主集羣的每一個RegionServer進程內部起了一個叫作ReplicationSource的線程來負責Replication,同時在備集羣的每一個RegionServer內部起了一個ReplicationSink的線程來負責接收Replication數據。ReplicationSource記錄須要同步的WAL隊列,而後不斷讀取WAL中的內容,同時能夠根據Replication的配置作一些過濾,好比是否要複製這個表的數據等,而後經過replicateWALEntry這個Rpc調用來發送給備集羣的RegionServer,備集羣的ReplicationSink線程則負責將收到的數據轉換爲put/delete操做,以batch的形式寫入到備集羣中。性能

由於是後臺線程異步的讀取WAL並複製到備集羣,因此這種Replication方式叫作異步Replication,正常狀況下備集羣收到最新寫入數據的延遲在秒級別。

串行Replication

串行Replication指的是:對於某個Region來講,嚴格按照主集羣的寫入順序複製到備集羣,其是一種特殊的Replication。同時默認的異步Replication不是串行的,主要緣由是Region是能夠移動的,好比HBase在進行負載均衡時移動Region。假設RegionA首先在RegionServer1上,而後其被移動到了RegionServer2上,因爲異步Replication是存在延遲的,因此RegionA的最後一部分寫入記錄尚未徹底複製到備集羣上。在Region移動到RegionServer2以後,其開始接收新的寫入請求,並由RegionServer2來複制到備集羣,因此在這個時候RegionServer1和RegionServer2會同時向備集羣進行復制,並且寫入記錄複製到備集羣的順序是不肯定的。

如上圖所示這種極端狀況下,還會致使主備集羣數據的不一致。好比RegionServer1上最後一個未同步的寫入操做是Put,而RegionA被移動到RegionServer2上的第一個寫入操做是Delete,在主集羣上其寫入順序是先Put後Delete,若是RegionServer2上的Delete操做先被複制到了備集羣,而後備集羣作了一次Major compaction,其會刪除掉這個Delete marker,而後Put操做才被同步到了備集羣,由於Delete已經被Major compact掉了,這個Put將永遠沒法被刪除,因此備集羣的數據將會比主集羣多。

解決這個問題的關鍵在於須要確保RegionServer2上的新寫入操做必須在RegionServer1上的寫入操做複製完成以後再進行復制。因此串行Replication引入了一個叫作Barrier的概念,每當Region open的時候,就會寫入一個新的Barrier,其值是Region open時讀到的最大SequenceId加1。SequenceId是HBase中的一個重要概念,每一個Region都有一個SequenceId,其隨着數據寫入嚴格遞增,同時SequenceId會隨着每次寫入操做一塊兒寫入到WAL中。因此當Region移動的時候,Region會在新的RegionServer從新打開,這時就會寫入一個新的Barrier,Region被移動屢次以後,就會寫入多個Barrier,來將Region的寫入操做劃分紅爲多個區間。同時每一個Region都維護了一個lastPushedSequenceId,其表明這個Region當前推送成功的最後一個寫操做的SequenceId,這樣就能夠根據Barrier列表和lastPushedSequenceId來判斷WAL中的一個寫入操做是否可以複製到備集羣了。


以上圖爲例,Pending的寫入記錄就須要等待lastPushedSequenceId推到Barrier2以後才能開始複製。因爲每一個區間之間只會有一個RegionServer來負責複製,因此只有和lastPushedSequenceId在同一個區間內的RegionServer才能進行復制,並在複製成功後不斷更新lastPushedSequenceId,而在lastPushedSequenceId以後各個區間的RegionServer則須要等待lastPushedSequenceId被推到本身區間的起始Barrier,而後才能開始複製,從而確保了Region的寫入操做能夠嚴格按照主集羣的寫入順序串行的複製到備集羣。

同步Replication

同步Replication是和異步Replication對稱的概念,其指的是主集羣的寫入操做必須被同步的寫入到備集羣中。異步Replication的最大問題在於複製是存在延遲的,因此在主集羣整集羣掛掉的狀況下,備集羣是沒有已經寫入的完整數據的,對於一致性要求較高的業務來講,是不能把讀寫徹底切到備集羣的,由於在這個時候可能存在部分最近寫入的數據沒法從備集羣讀到。因此同步Replication的核心思路就是在寫入主集羣WAL的同時,在備集羣上寫入一份RemoteWAL,只有同時在主集羣的WAL和備集羣的RemoteWAL寫入成功了,纔會返回給Client說寫入成功。這樣當主集羣掛掉的時候,即可以在備集羣上根據Remote WAL來回放出來主集羣上全部寫入記錄,從而確保備集羣和主集羣數據的一致。

須要注意的是,同步Replication是在異步Replication的基礎之上的,也就是說異步Replication的複製鏈路還會繼續保留,同時增長了新的寫Remote WAL的步驟。對於具體的實現細節來講,首先是增長了一個Sync replication state的概念,其總共有三個狀態, 分別是Active,Downgrade Active和Standby。這幾個狀態的轉換關係以下圖所示,Standby在提主的時候須要首先提高爲Downgrade Active,而後才能提高爲Active。可是Active是能夠直接降級爲Standby的。目前這個狀態是保存在ReplicationPeerConfig中的, 其表示一個集羣在這個ReplicationPeer中處於哪一個狀態。

而後實現了一個DualAsyncFSWAL來同時寫主集羣的WAL和備份集羣的Remote WAL。寫WAL的操做是對於HDFS的rpc請求,其會有三種結果: 成功,失敗或者超時。當超時的時候,對於HBase來講結果是不肯定的,即數據有可能成功寫入到WAL或Remote WAL裏了,也有可能沒有。只有同時寫成功或者同時寫失敗的時候,主集羣和備集羣纔會有同樣的WAL,若是是主集羣寫WAL成功,寫Remote WAL失敗或者超時,這時候主集羣WAL裏的數據就有可能比備集羣的Remote WAL多。相反若是寫備集羣Remote WAL成功了,而主集羣的WAL寫失敗或者超時了,備集羣的Remote WAL裏的數據就有可能比主集羣多。當兩邊都超時的時候, 就不肯定那邊多了。因此同步複製的關鍵就在於在上述狀況下,如何確保主備集羣數據的最終一致。即在切換主備集羣的時候,Client應該始終從主備集羣看到一致的數據。並且在主備沒有達到一致的中間狀態時,須要一些限制來確保Client無法讀到這種中間不一致的結果。因此總結一下就是主備集羣最終一致,但對於Client來講是強一致,即成功寫入的數據不管主備集羣都要必定能讀到。具體的實現細節能夠參考HBaseCon Asia 2018:HBase at Xiaomi[1]。



Async Replication

Sync Replication

Read Path

No affect

No affect

Write Path

No affect

Write extra remote WAL

Network bandwidth

100% for async replication.

100% for async + 100% for remote WAL.

Storage space

No affect

Need extra space for remote WAL

Eventual Consistency

No if active cluster crashed

Yes

Availability

Unavailable when master crash

Few time for waiting replay remote log.

Operational Complexity

Simple

More complex, Need to transition cluster state by hand or your services.

對比異步複製來看,同步複製主要是影響的寫路徑,從咱們的測試結果上來看,大概會有14%的性能降低,後續計劃在HBASE-20422[2]中進行優化。

自定義Replication Endpoint

除了上述3種Replication以外,HBase還支持插件式的Replication Endpoint,能夠自定義Replication Endpoint來實現各類各樣的功能。具體到小米來講,咱們實現了能夠在不一樣表之間的Replication Endpoint,好比能夠將主集羣的表A複製到備集羣的表B,其應用場景有集羣遷移,Namespace更換或者表名更換等。同時爲了實現Point-in-time Recovery,咱們作了能夠同步數據到小米消息隊列Talos的Replication Endpoint,當出現須要恢復某個時間點t1的場景時,能夠首先找到冷備中距離t1最近的一個的Snapshot進行恢復,而後將消息隊列中的數據來回放到t1時間點,從而作到Point-in-time Recovery。最後,咱們還作了相似DynamoDB Stream的功能[3],將用戶表的修改日誌複製到用戶本身的消息隊列中,而後用戶能夠依賴這份數據來作一些流式的數據處理。此外,HBase Read Replica功能,目前的一種實現方案就是依賴HBase Replication,經過插件式的Replication Endpoint將主Replica的數據複製到其餘Read Replica中,詳見HBASE-10070[4]。

以上就是HBase中各類各樣的Replication,若有錯誤,歡迎指正。

同時歡迎你們在業務場景中按需進行使用,你們也能夠根據本身的特殊場景自定義新的Replication Endpoint,並歡迎貢獻到社區。

參考連接:
https://www.slideshare.net/MichaelStack4/hbaseconasia2018-track13-hbase-at-xiaomi
https://jira.apache.org/jira/browse/HBASE-20422
https://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/Streams.html
https://issues.apache.org/jira/browse/HBASE-10070
mapr.com/blog/in-dep…

本文首發於公衆號「小米雲技術」,轉載請標明出處,點擊查看原文連接

相關文章
相關標籤/搜索