天天看點

Spark技術内幕:Master基于ZooKeeper的High Availability(HA)源碼實作

     如果spark的部署方式選擇standalone,一個采用master/slaves的典型架構,那麼master是有spof(單點故障,single point of failure)。spark可以選用zookeeper來實作ha。

     zookeeper提供了一個leader election機制,利用這個機制可以保證雖然叢集存在多個master但是隻有一個是active的,其他的都是standby,當active的master出現故障時,另外的一個standby master會被選舉出來。由于叢集的資訊,包括worker, driver和application的資訊都已經持久化到檔案系統,是以在切換的過程中隻會影響新job的送出,對于正在進行的job沒有任何的影響。加入zookeeper的叢集整體架構如下圖所示。

Spark技術内幕:Master基于ZooKeeper的High Availability(HA)源碼實作

master在啟動時,會根據啟動參數來決定不同的master故障重新開機政策:

zookeeper實作ha

filesystem:實作master無資料丢失重新開機,叢集的運作時資料會儲存到本地/網絡檔案系統上

丢棄所有原來的資料重新開機

master::prestart()可以看出這三種不同邏輯的實作。

recovery_mode是一個字元串,可以從spark-env.sh中去設定。

如果不設定spark.deploy.recoverymode的話,那麼叢集的所有運作資料在master重新開機是都會丢失,這個結論是從blackholepersistenceengine的實作得出的。

它把所有的接口實作為空。persistenceengine是一個trait。作為對比,可以看一下zookeeper的實作。

spark使用的并不是zookeeper的api,而是使用的org.apache.curator.framework.curatorframework 和 org.apache.curator.framework.recipes.leader.{leaderlatchlistener, leaderlatch} 。curator在zookeeper上做了一層很友好的封裝。

簡單總結一下參數的設定,通過上述代碼的分析,我們知道為了使用zookeeper至少應該設定一下參數(實際上,僅僅需要設定這些參數。通過設定spark-env.sh:

各個參數的意義:

參數

預設值

含義

spark.deploy.recoverymode

none

恢複模式(master重新啟動的模式),有三種:1, zookeeper, 2, filesystem, 3 none

spark.deploy.zookeeper.url

zookeeper的server位址

spark.deploy.zookeeper.dir

/spark

zookeeper 儲存叢集中繼資料資訊的檔案目錄,包括worker,driver和application。

curatorframework極大的簡化了zookeeper的使用,它提供了high-level的api,并且基于zookeeper添加了很多特性,包括

自動連接配接管理:連接配接到zookeeper的client有可能會連接配接中斷,curator處理了這種情況,對于client來說自動重連是透明的。

簡潔的api:簡化了原生态的zookeeper的方法,事件等;提供了一個簡單易用的接口。

recipe的實作(更多介紹請點選recipes):

leader的選擇

共享鎖

緩存和監控

分布式的隊列

分布式的優先隊列

curatorframeworks通過curatorframeworkfactory來建立線程安全的zookeeper的執行個體。

curatorframeworkfactory.newclient()提供了一個簡單的方式來建立zookeeper的執行個體,可以傳入不同的參數來對執行個體進行完全的控制。擷取執行個體後,必須通過start()來啟動這個執行個體,在結束時,需要調用close()。

需要關注的還有兩個recipe:org.apache.curator.framework.recipes.leader.{leaderlatchlistener, leaderlatch}。

首先看一下leaderlatchlistener,它在leaderlatch狀态變化的時候被通知:

在該節點被選為leader的時候,接口isleader()會被調用

在節點被剝奪leader的時候,接口notleader()會被調用

由于通知是異步的,是以有可能在接口被調用的時候,這個狀态是準确的,需要确認一下leaderlatch的hasleadership()是否的确是true/false。這一點在接下來spark的實作中可以得到展現。

leaderlatch負責在衆多連接配接到zookeeper cluster的競争者中選擇一個leader。leader的選擇機制可以看zookeeper的具體實作,leaderlatch這是完成了很好的封裝。我們隻需要要知道在初始化它的執行個體後,需要通過

通過addlistener可以将我們實作的listener添加到leaderlatch。在listener裡,我們在兩個接口裡實作了被選為leader或者被剝奪leader角色時的邏輯即可。

實際上因為有curator的存在,spark實作master的ha就變得非常簡單了,zookeeperleaderelectionagent實作了接口leaderlatchlistener,在isleader()确認所屬的master被選為leader後,向master發送消息electedleader,master會将自己的狀态改為alive。當noleader()被調用時,它會向master發送消息revokedleadership時,master會關閉。

在prestart中,啟動了leaderlatch來處理選舉zk中的leader。就如在上節分析的,主要的邏輯在isleader和noleader中。

updateleadershipstatus的邏輯很簡單,就是向master發送消息。

為了解決standalone模式下的master的spof,spark采用了zookeeper提供的選舉功能。spark并沒有采用zookeeper原生的java api,而是采用了curator,一個對zookeeper進行了封裝的架構。采用了curator後,spark不用管理與zookeeper的連接配接,這些對于spark來說都是透明的。spark僅僅使用了100行代碼,就實作了master的ha。當然了,spark是站在的巨人的肩膀上。誰又會去重複發明輪子呢?

請您支援:

如果你看到這裡,相信這篇文章對您有所幫助。如果是的話,請為本文投一下票吧: 點選投票,多謝。如果您已經在投票頁面,請點選下面的投一票吧!

btw,即使您沒有csdn的帳号,可以使用第三方登入的,包括微網誌,qq,gmail,github,百度,等。

繼續閱讀