1. 程式人生 > >hadoop zookeeper 配置HA

hadoop zookeeper 配置HA

原文地址:ZooKeeper是一個分散式的,開放原始碼的分散式應用程式協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要元件。它是一個為分散式應用提供一致性服務的軟體,提供的功能包括:配置維護、域名服務、分散式同步、組服務等。

非HA弊端

HDFS叢集的分散式儲存是靠namenode節點(namenode負責響應客戶端請求)來實現。在非HA叢集中一旦namenode宕機,雖然元資料不會丟失,但整個叢集將無法對外提供服務,導致HDFS服務的可靠性不高,這在實際應用場景中顯然是不可行的。

HA機制

已知導致服務可靠性不高的原因是namenode節點宕機,那麼怎麼才能避免這個namenode節點宕機呢?一個容易想到的解決方案是部署兩臺namenode節點,形成主備模式(active/standby模式),這樣一旦active節點宕機,standby節點立即切換到active模式。事實上HA機制就是採取的這種方案。要想實現該機制,需要解決以下問題:

1.為什麼選擇主備模式,而不是主主模式(active/active模式),也即讓兩個namenode節點都響應客戶端的請求

        一個顯然的前提是,兩臺namenode節點需要儲存一致的元資料。

        我們知道namenode節點是用來管理這些元資料的,響應客戶端請求時(上傳)需要增加元資料資訊,如果使用主主模式,那麼兩個節點都將對元資料進行寫操作,怎麼同步是個很困難的問題。因此,只能有一臺機器響應請求,也即處在active狀態的節點(可稱為主節點),而另一臺namenode在主節點正常工作情況下僅用來同步active節點的元資料資訊,這個namenode稱為備用節點(處在standby狀態),可見,要解決的問題主要是怎麼同步active節點的元資料資訊。

2.怎麼同步兩個namenode節點的元資料

      響應客戶端請求的是active節點,因此只有active節點儲存了最新的元資料。元資料分為兩部分,一部分是剛寫入新的元資料(edits),另一部分是合併後的較舊的(fsimage)。HA機制解決同步問題的方法是將active節點新寫入的edits元資料放在zookeeper叢集上(zookeeper叢集主要功能是實現少量資料的分散式同步管理),standby節點在active節點正常情況下只需要將zookeeper叢集上edits檔案同步到自己的fsimage中就可以。

       hadoop框架為這個叢集專門寫了個分散式應用qjournal(依賴zookeeper實現),實現qjournal的節點稱為journalnode。

3.怎麼感知active節點是否宕機,並將standby節點快速切換到active狀態?

        解決方案是專門在namenode節點上啟動一個監控程序,時刻監控namenode的狀態。對於處在active狀態的namenode,如果發現不正常就向zookeeper叢集中寫入一些資料。對於處在standby狀態的namenode,監控程序從zookeeper叢集中讀資料,從而感知到active節點是否正常。如果發現異常,監控程序負責將standby狀態切換到active狀態。這個監控程序在hadoop中叫做zkfc(依賴zookeeper實現)。

4.如何在狀態切換時避免brain split(腦裂)?

        腦裂:active namenode工作不正常後,zkfc在zookeeper中寫入一些資料,表明異常,這時standby namenode中的zkfc讀到異常資訊,並將standby節點置為active。但是,如果之前的active namenode並沒有真的死掉,出現了假死(死了一會兒後又正常了,哈哈,是不是很搞笑),這樣,就有兩臺namenode同時工作了。這種現象稱為腦裂。

        解決方案:standby namenode感知到主用節點出現異常後並不會立即切換狀態,zkfc會首先通過ssh遠端殺死active節點的 namenode程序(kill -9 程序號)。但是(這樣還不行,驚訝),如果kill指令沒有執行成功咋辦??如果在一段時間內沒有收到執行成功的回執,standby節點會執行一個自定義指令碼,儘量保證不會出現腦裂問題!這個機制在hadoop中稱為fencing(包括ssh傳送kill指令,執行自定義指令碼兩道保障)

解決上訴問題以後,基本上就實現了hadoop HA 。

HA實現
1.HA叢集規劃
主機名軟體程序
sempplsl-02jdk,hadoop,zookeeperQuorumPeerMain(zookeeper),journalnode,datanode,nodemanager
sempplsl-03jdk,hadoop,zookeeperQuorumPeerMain(zookeeper),journalnode,datanode,nodemanager
sempplsl-04jdk,hadoop,zookeeperQuorumPeerMain(zookeeper),journalnode,datanode,nodemanager
sempplsl-05jdk,hadoopnamenode,zkfc(active)
sempplsl-06jdk,hadoopnamenode,zkfc
sempplsl-07jdk,hadoopresourcemanager
sempplsl-08jdk,hadoopresourcemanager

(注:datanode,nodemanager一般放到一起。journalnode依賴zookeeper來實現,因此QuorumPeerMain(zookeeper),journalnode必須放一起!)

2.hadoop HA叢集配置

core-site.xml   ---->

<property>
<!-- 指定hdfs的nameservice為ns1 -->
<name>fs.defaultFS</name>
<value>hdfs://ns1/</value>
</property>
<!-- 指定hadoop臨時目錄 -->	
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/app/hadoop-2.4.1/tmp</value>
</property>
<!-- 指定zookeeper地址 -->				
<property>
<name>ha.zookeeper.quorum</name>
<value>sempplsl-02:2181,sempplsl-03:2181,sempplsl-04:2181</value>
</property>

hdfs-site.xml  --->

<!--指定hdfs的nameservice為ns1,需要和core-site.xml中的保持一致 -->
<property>
<name>dfs.nameservices</name>
<value>ns1</value>
</property>
<!-- ns1下面有兩個NameNode,分別是nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.ns1</name>
<value>nn1,nn2</value>
</property>
<!-- nn1的RPC通訊地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn1</name>
<value>sempplsl-05:9000</value>
</property>
<!-- nn1的http通訊地址 -->
<property>
<name>dfs.namenode.http-address.ns1.nn1</name>
<value>sempplsl-05:50070</value>
</property>
<!-- nn2的RPC通訊地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn2</name>
<value>sempplsl-06:9000</value>
</property>
<!-- nn2的http通訊地址 -->
<property>
<name>dfs.namenode.http-address.ns1.nn2</name>
<value>sempplsl-06:50070</value>
</property>
<!-- 指定NameNode的元資料在JournalNode上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://sempplsl-02:8485;sempplsl-03:8485;sempplsl-04:8485/ns1</value>
</property>
<!-- 指定JournalNode在本地磁碟存放資料的位置 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/home/hadoop/app/hadoop-2.4.1/journaldata</value>
</property>
<!-- 開啟NameNode失敗自動切換 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 配置失敗自動切換實現方式 -->
<property>
<name>dfs.client.failover.proxy.provider.ns1</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 配置隔離機制方法,多個機制用換行分割,即每個機制暫用一行-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
shell(/bin/true)
</value>
</property>
<!-- 使用sshfence隔離機制時需要ssh免登陸 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
<!-- 配置sshfence隔離機制超時時間 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>

yarn-site.xml  --->

<!-- 開啟RM高可用 -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!-- 指定RM的cluster id -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yrc</value>
</property>
<!-- 指定RM的名字 -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!-- 分別指定RM的地址 -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>sempplsl-07</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>sempplsl-08</value>
</property>
<!-- 指定zk叢集地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>sempplsl-02:2181,sempplsl-02:2181,sempplsl-02:2181</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

marped-site.xml --->

<!-- 指定mr框架為yarn方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

3.HA叢集啟動

3.1. 修改slaves檔案

    slaves檔案儲存子節點的位置,要在sempplsl-05上啟動hdfs,按照叢集配置,需要指定datanode在sempplsl-02,sempplsl-03,sempplsl-04上,方法是進入sempplsl-05機器中的hadoop-2.4.1/etc/hadoop安裝資料夾。

    此外,在sempplsl-07上啟動yarn,按照叢集配置,需要指定nodemanager在sempplsl-02,sempplsl-03,sempplsl-04上,方法同上。

3.2.配置無金鑰登陸

    配置sempplsl-05到sempplsl-02,sempplsl-03,sempplsl-04,sempplsl-06的無金鑰登陸;(ssh-keygen -t rsa,ssh-copy-id 目標主機)

    配置sempplsl-07到sempplsl-02,sempplsl-03,sempplsl-04,sempplsl-08的無金鑰登陸;

3.3.將配置好的hadoop copy到叢集其它節點

    scp -r 

3.4.啟動zookeeper叢集

    分別在sempplsl-02,sempplsl-03,sempplsl-04機器上執行啟動指令:./zkServer.sh start  

    檢視zookeeper狀態:./zkServer.sh status, 正確的狀態是一個leader,兩個follower。

3.5.啟動journalnode

    分別在sempplsl-02,sempplsl-03,sempplsl-04機器上執行啟動指令:sbin/hadoop-daemon.sh start journalnode。

    啟動成功後會多出一個JournalNode程序。

3.6. 格式化HDFS

    在sempplsl-05上執行格式化指令:hadoop namenode -format 

3.7.格式化zkfc

    在sempplsl-05上執行格式化指令: hdfs zkfc -formatZK

    格式化成功後會在zookeeper叢集建立新的檔案路徑(該路徑下存放zkfc監控namenode節點的資訊)

3.8.啟動HDFS

    在sempplsl-05上執行:start-dfs.sh。

3.9.啟動yarn

   在sempplsl-07上執行sbin/start-yarn.sh

   在sempplsl-08上執行./yarn-daemon.sh start resourcemanager

至此,HA叢集啟動成功!