1. 程式人生 > ><zk在大型分布式系統中的應用>

<zk在大型分布式系統中的應用>

行數據 三種 hbase 開始 並且 基於內存 2-2 方案 體系

Hadoop

  • 在hadoop中,zk主要用來實現HA(High Availability)。這部分邏輯主要集中在hadoop common的HA模塊中,HDFS的NameNode和Yarn的ResourceManager都是基於此HA模塊來實現自己的HA功能的。同時,在YARN中又特別提供了zk來存儲應用的運行狀態。

YARN

  • Yarn主要由ResourceManager、NodeManager、ApplicationMaster和Container四部分組成。
  • 其中最核心的就是RM,它作為全局的資源管理器,負責整個系統的資源管理和分配。

RM單點問題

  • RM是YARN中非常復雜的一個組件,負責集群中所有資源的統一管理和分配,同時接受各個NM的資源匯報信息,並把這些信息按照一定的策略分配給各個app。
  • ResourceManager HA的解決方案就是使用 Active/Standby模式的RM HA架構
    技術分享
  • 可以看到,在運行期間會有多個RM存在,但只有一個處於Active狀態,其他的是standby。當active節點無法正常工作時,其余處於standby的節點則會通過競爭選舉產生新的節點。

主備切換

    • RM使用基於zk實現的ActiveStandbyElector組件來確定RM的狀態:Active或Standby。
      具體做法如下:
      1. 創建鎖節點:在zk上有一個類似於/yarn-leader-election/pseudo-yarn-rm-cluster的鎖節點,所有rm在啟動時都會去競爭一個lock子節點/yarn-leader-election/pseudo-yarn-rm-cluster/ActiveStandbyElectorLock,該節點是臨時節點。
      2. 註冊Watcher監聽:所有standby狀態的rm都會向/yarn-leader-election/pseudo-yarn-rm-cluster/ActiveStandbyElectorLock節點註冊一個節點變更的Watcher監聽,利用臨時節點的特性,能快速感知到Active狀態的RM的運行狀態。
      3. 主備切換:當active節點不可用時,其對應zk上的Lock節點也會隨之被刪除,其他standby狀態的rm都會接收到zk server的watcher事件通知,然後重復步驟1。
    • 以上,實際上就是通過臨時節點 + Watcher事件通知來實現的。
    • HDFS中的NameNode和RM模塊都是使用ActiveStandbyElector組件來實現各自的HA的。

Fencing(隔離)

  • 在分布式環境中,經常會出現諸如單機“假死”的情況。所謂“假死”是指機器由於網絡閃斷或是自身負載過高(常見的有GC占用時間過長或CPU的負載過高等)而導致無法正常地對外進行及時響應
  • 在上述主備切換過程中,我們假設RM集群由rm1和rm2組成,且rm1為active,rm2為standby。某一刻rm1發生“假死”現象,此時zk認為rm1掛了,從而主備切換,rm2稱為active。但是隨後,rm1恢復了正常,其依然認為自己還處於active。那麽就出現了我們常說的分布式“腦裂”(Brain-Split)現象,即存在多個處於Active狀態的rm各司其職。
  • Yarn引入了Fencing機制來解決上述問題,即借助zk數據節點的ACL權限控制機制來實現不同rm之間的隔離
  • 具體做法很簡單:在主備切換過程中,多個rm之間通過競爭創建鎖節點來實現主備狀態的確定。這個過程中,有一點需要改進:創建的根節點必須攜帶zk的ACL信息,目的是為了獨占該根節點,以防止其他RM對該節點進行更新。
  • 具體來說:
    • RM1出現假死之後,zk就會將其創建的鎖節點移除,此時RM2會創建相應的鎖節點,並切換為Active狀態。RM1恢復之後,會試圖去更新zk的相關數據,但是此時發現自己沒有權限更新zk的相關數據節點。從而rm1自動切換到Standby狀態。

RM狀態存儲

  • 在RM中,RMStateStore能夠存儲一些RM內部狀態信息,包括Application以及它們的Attempts信息、Delegatioln Token及Version Information等。
  • RMStateStore中絕大多數信息都是不需要持久化存儲,因為很容易從上下文信息中將其重構出來。
  • 在存儲的設計方案中,提供了三種可能的實現,分別如下:
    • 基於內存實現,一般用於日常開發測試;
    • 基於文件系統的實現,如HDFS;
    • 基於zk的實現
  • 由於這些狀態數據量都不大,因此hadoop官方建議基於zk來實現狀態信息存儲
  • 在zk上,rm的狀態信息都存儲在/rmstore這個根節點上,其數據節點的組織結構如下:
    技術分享

HBase

  • HBase是一個基於Hadoop文件系統設計的面向海量數據的高可靠性、高性能、面向列、可伸縮的分布式存儲系統。
  • 與大部分分布式NoSQL數據庫不同的是,HBase針對數據寫入具有強一致性,甚至包括索引列也實現了強一致性。
  • HBase整體架構如下圖:
    技術分享
  • 可以看到,在整個HBase架構體系中,zk是串聯起HBase集群與client的關鍵所在。
  • 早期Hbase沒有引入zk時,存在一系列問題:
    • RegionServer掛掉時,系統無法及時得知信息,client也無法知曉,因此服務難以遷移至其他RegionServer上
    • 類似的問題都是缺少相應的分布式協調組件
  • 下面從以下幾個方面講解zk在HBase中的應用場景。

系統冗錯

  • (系統冗錯其實就是監控rs
  • 當HBase啟動時,每個RegionServer都會到zk的/hbase/rs節點下創建一個信息節點(rs狀態節點),例如/hbase/rs/[Hostname],同時HMaster會監聽該節點。
  • 當某個rs掛掉時,zk會因為在一段時間內無法接受其心跳信息(即Session失效),而刪除掉該rs對應的rs狀態節點。同時,HMaster收到zk的NodeDelete通知,並立即開始冗錯工作:
    • HMaster會將該RegionServer所處理的數據分片(Region)重新路由到其他節點上,並記錄到Meta信息中供client查詢
  • 那麽,為什麽不直接讓HMaster來負責RegionServer的監控呢?是因為通過心跳機制來管理rs狀態會使HMaster的負載隨著系統容量而不斷增大。並且,HMaster可能掛掉,因此數據還需要持久化。

RootRegion管理

  • 對HBase集群而言,數據存儲的位置信息是記錄在元數據分片,也就是RootRegion上的。每次client發起新的請求,需要知道數據的位置,就會去查詢RootRegion,而RootRegion自身的位置是記錄在zk上的。當RootRegion發生變化,比如Region的手工移動、Balance或是RootRegion所在server發生故障等時,就能通過zk來感知到這一變化並做出一系列容災措施。

Region狀態管理

  • Region是HBase中數據的物理切片,每個Region中記錄了全局數據的一小部分。
  • 對一個分布式系統而言,Region是會經常發生變更的。一旦Region發生移動,它必然會經歷Offline和重新Online的過程。
  • Offline期間數據是不能被訪問的,並且Region的這個狀態必須被全局知曉,否則可能會出現事務性的異常。

分布式SplitLog任務管理

  • 當某臺RS掛掉時,由於總有一部分新寫入的數據還沒有持久化到HFile中,因此在遷移該RegionServer的服務時,一個重要的工作就是從HLog中恢復這部分還在內存中的數據(WAL)。
  • 而這部分工作最關鍵的一步就是SpitLog,即HMaster需要遍歷該RS的HLog,並按Region切分成小塊移動到新地址下,並進行數據的Replay。
  • 由於單個RS的日誌量相對龐大(可能有數千個Region,上GB的日誌),一個快速恢復的可行方案就是將這個處理HLog的任務分配給多臺rs來共同處理。
  • 因此需要一個持久化組件來輔助HMaster完成任務的分配。當前的做法是,在zk上創建一個splitlog節點,將rs和待處理的region之間的映射關系存放到該節點。然後各個rs到該節點上領取任務並在執行後將成功or失敗的信息更新到節點。
  • 整個過程中,zk擔負了分布式集群中相互通知和信息持久化的角色。

Kafka

<zk在大型分布式系統中的應用>