如果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的叢集整體架構如下圖所示。
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,百度,等。