Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

一愤兵、高可用簡介

Hadoop 高可用 (High Availability) 分為 HDFS 高可用和 YARN 高可用,兩者的實現(xiàn)基本類似,但 HDFS NameNode 對數(shù)據(jù)存儲及其一致性的要求比 YARN ResourceManger 高得多肃廓,所以它的實現(xiàn)也更加復(fù)雜,故下面先進行講解:

1.1 高可用整體架構(gòu)

HDFS 高可用架構(gòu)如下:

https://github.com/heibaiying

圖片引用自:https://www.edureka.co/blog/how-to-set-up-hadoop-cluster-with-hdfs-high-availability/

HDFS 高可用架構(gòu)主要由以下組件所構(gòu)成:

  • Active NameNode 和 Standby NameNode:兩臺 NameNode 形成互備诲泌,一臺處于 Active 狀態(tài)盲赊,為主 NameNode,另外一臺處于 Standby 狀態(tài)敷扫,為備 NameNode哀蘑,只有主 NameNode 才能對外提供讀寫服務(wù)。

  • 主備切換控制器 ZKFailoverController:ZKFailoverController 作為獨立的進程運行葵第,對 NameNode 的主備切換進行總體控制绘迁。ZKFailoverController 能及時檢測到 NameNode 的健康狀況,在主 NameNode 故障時借助 Zookeeper 實現(xiàn)自動的主備選舉和切換羹幸,當(dāng)然 NameNode 目前也支持不依賴于 Zookeeper 的手動主備切換脊髓。

  • Zookeeper 集群:為主備切換控制器提供主備選舉支持。

  • 共享存儲系統(tǒng):共享存儲系統(tǒng)是實現(xiàn) NameNode 的高可用最為關(guān)鍵的部分栅受,共享存儲系統(tǒng)保存了 NameNode 在運行過程中所產(chǎn)生的 HDFS 的元數(shù)據(jù)。主 NameNode 和 NameNode 通過共享存儲系統(tǒng)實現(xiàn)元數(shù)據(jù)同步恭朗。在進行主備切換的時候屏镊,新的主 NameNode 在確認元數(shù)據(jù)完全同步之后才能繼續(xù)對外提供服務(wù)。

  • DataNode 節(jié)點:除了通過共享存儲系統(tǒng)共享 HDFS 的元數(shù)據(jù)信息之外痰腮,主 NameNode 和備 NameNode 還需要共享 HDFS 的數(shù)據(jù)塊和 DataNode 之間的映射關(guān)系而芥。DataNode 會同時向主 NameNode 和備 NameNode 上報數(shù)據(jù)塊的位置信息。

1.2 基于 QJM 的共享存儲系統(tǒng)的數(shù)據(jù)同步機制分析

目前 Hadoop 支持使用 Quorum Journal Manager (QJM) 或 Network File System (NFS) 作為共享的存儲系統(tǒng)膀值,這里以 QJM 集群為例進行說明:Active NameNode 首先把 EditLog 提交到 JournalNode 集群棍丐,然后 Standby NameNode 再從 JournalNode 集群定時同步 EditLog误辑,當(dāng) Active NameNode 宕機后, Standby NameNode 在確認元數(shù)據(jù)完全同步之后就可以對外提供服務(wù)歌逢。

需要說明的是向 JournalNode 集群寫入 EditLog 是遵循 “過半寫入則成功” 的策略巾钉,所以你至少要有 3 個 JournalNode 節(jié)點,當(dāng)然你也可以繼續(xù)增加節(jié)點數(shù)量秘案,但是應(yīng)該保證節(jié)點總數(shù)是奇數(shù)砰苍。同時如果有 2N+1 臺 JournalNode,那么根據(jù)過半寫的原則阱高,最多可以容忍有 N 臺 JournalNode 節(jié)點掛掉赚导。

https://github.com/heibaiying

1.3 NameNode 主備切換

NameNode 實現(xiàn)主備切換的流程下圖所示:

https://github.com/heibaiying
  1. HealthMonitor 初始化完成之后會啟動內(nèi)部的線程來定時調(diào)用對應(yīng) NameNode 的 HAServiceProtocol RPC 接口的方法,對 NameNode 的健康狀態(tài)進行檢測赤惊。
  2. HealthMonitor 如果檢測到 NameNode 的健康狀態(tài)發(fā)生變化吼旧,會回調(diào) ZKFailoverController 注冊的相應(yīng)方法進行處理。
  3. 如果 ZKFailoverController 判斷需要進行主備切換未舟,會首先使用 ActiveStandbyElector 來進行自動的主備選舉圈暗。
  4. ActiveStandbyElector 與 Zookeeper 進行交互完成自動的主備選舉。
  5. ActiveStandbyElector 在主備選舉完成后处面,會回調(diào) ZKFailoverController 的相應(yīng)方法來通知當(dāng)前的 NameNode 成為主 NameNode 或備 NameNode厂置。
  6. ZKFailoverController 調(diào)用對應(yīng) NameNode 的 HAServiceProtocol RPC 接口的方法將 NameNode 轉(zhuǎn)換為 Active 狀態(tài)或 Standby 狀態(tài)。

1.4 YARN高可用

YARN ResourceManager 的高可用與 HDFS NameNode 的高可用類似魂角,但是 ResourceManager 不像 NameNode 昵济,沒有那么多的元數(shù)據(jù)信息需要維護,所以它的狀態(tài)信息可以直接寫到 Zookeeper 上野揪,并依賴 Zookeeper 來進行主備選舉访忿。

https://github.com/heibaiying

二、集群規(guī)劃

按照高可用的設(shè)計目標(biāo):需要保證至少有兩個 NameNode (一主一備) 和 兩個 ResourceManager (一主一備) 斯稳,同時為滿足“過半寫入則成功”的原則海铆,需要至少要有 3 個 JournalNode 節(jié)點。這里使用三臺主機進行搭建挣惰,集群規(guī)劃如下:

https://github.com/heibaiying

三卧斟、前置條件

四竖幔、集群配置

4.1 下載并解壓

下載 Hadoop板乙。這里我下載的是 CDH 版本 Hadoop,下載地址為:http://archive.cloudera.com/cdh5/cdh/5/

# tar -zvxf hadoop-2.6.0-cdh5.15.2.tar.gz 

4.2 配置環(huán)境變量

編輯 profile 文件:

# vim /etc/profile

增加如下配置:

export HADOOP_HOME=/usr/app/hadoop-2.6.0-cdh5.15.2
export  PATH=${HADOOP_HOME}/bin:$PATH

執(zhí)行 source 命令拳氢,使得配置立即生效:

# source /etc/profile

4.3 修改配置

進入 ${HADOOP_HOME}/etc/hadoop 目錄下募逞,修改配置文件蛋铆。各個配置文件內(nèi)容如下:

1. hadoop-env.sh

# 指定JDK的安裝位置
export JAVA_HOME=/usr/java/jdk1.8.0_201/

2. core-site.xml

<configuration>
    <property>
        <!-- 指定 namenode 的 hdfs 協(xié)議文件系統(tǒng)的通信地址 -->
        <name>fs.defaultFS</name>
        <value>hdfs://hadoop001:8020</value>
    </property>
    <property>
        <!-- 指定 hadoop 集群存儲臨時文件的目錄 -->
        <name>hadoop.tmp.dir</name>
        <value>/home/hadoop/tmp</value>
    </property>
    <property>
        <!-- ZooKeeper 集群的地址 -->
        <name>ha.zookeeper.quorum</name>
        <value>hadoop001:2181,hadoop002:2181,hadoop002:2181</value>
    </property>
    <property>
        <!-- ZKFC 連接到 ZooKeeper 超時時長 -->
        <name>ha.zookeeper.session-timeout.ms</name>
        <value>10000</value>
    </property>
</configuration>

3. hdfs-site.xml

<configuration>
    <property>
        <!-- 指定 HDFS 副本的數(shù)量 -->
        <name>dfs.replication</name>
        <value>3</value>
    </property>
    <property>
        <!-- namenode 節(jié)點數(shù)據(jù)(即元數(shù)據(jù))的存放位置,可以指定多個目錄實現(xiàn)容錯放接,多個目錄用逗號分隔 -->
        <name>dfs.namenode.name.dir</name>
        <value>/home/hadoop/namenode/data</value>
    </property>
    <property>
        <!-- datanode 節(jié)點數(shù)據(jù)(即數(shù)據(jù)塊)的存放位置 -->
        <name>dfs.datanode.data.dir</name>
        <value>/home/hadoop/datanode/data</value>
    </property>
    <property>
        <!-- 集群服務(wù)的邏輯名稱 -->
        <name>dfs.nameservices</name>
        <value>mycluster</value>
    </property>
    <property>
        <!-- NameNode ID 列表-->
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2</value>
    </property>
    <property>
        <!-- nn1 的 RPC 通信地址 -->
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>
        <value>hadoop001:8020</value>
    </property>
    <property>
        <!-- nn2 的 RPC 通信地址 -->
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>hadoop002:8020</value>
    </property>
    <property>
        <!-- nn1 的 http 通信地址 -->
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>hadoop001:50070</value>
    </property>
    <property>
        <!-- nn2 的 http 通信地址 -->
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>hadoop002:50070</value>
    </property>
    <property>
        <!-- NameNode 元數(shù)據(jù)在 JournalNode 上的共享存儲目錄 -->
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://hadoop001:8485;hadoop002:8485;hadoop003:8485/mycluster</value>
    </property>
    <property>
        <!-- Journal Edit Files 的存儲目錄 -->
        <name>dfs.journalnode.edits.dir</name>
        <value>/home/hadoop/journalnode/data</value>
    </property>
    <property>
        <!-- 配置隔離機制刺啦,確保在任何給定時間只有一個 NameNode 處于活動狀態(tài) -->
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence</value>
    </property>
    <property>
        <!-- 使用 sshfence 機制時需要 ssh 免密登錄 -->
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/root/.ssh/id_rsa</value>
    </property>
    <property>
        <!-- SSH 超時時間 -->
        <name>dfs.ha.fencing.ssh.connect-timeout</name>
        <value>30000</value>
    </property>
    <property>
        <!-- 訪問代理類,用于確定當(dāng)前處于 Active 狀態(tài)的 NameNode -->
        <name>dfs.client.failover.proxy.provider.mycluster</name>
        <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
    </property>
    <property>
        <!-- 開啟故障自動轉(zhuǎn)移 -->
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>
</configuration>

4. yarn-site.xml

<configuration>
    <property>
        <!--配置 NodeManager 上運行的附屬服務(wù)透乾。需要配置成 mapreduce_shuffle 后才可以在 Yarn 上運行 MapReduce 程序洪燥。-->
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
    <property>
        <!-- 是否啟用日志聚合 (可選) -->
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
    <property>
        <!-- 聚合日志的保存時間 (可選) -->
        <name>yarn.log-aggregation.retain-seconds</name>
        <value>86400</value>
    </property>
    <property>
        <!-- 啟用 RM HA -->
        <name>yarn.resourcemanager.ha.enabled</name>
        <value>true</value>
    </property>
    <property>
        <!-- RM 集群標(biāo)識 -->
        <name>yarn.resourcemanager.cluster-id</name>
        <value>my-yarn-cluster</value>
    </property>
    <property>
        <!-- RM 的邏輯 ID 列表 -->
        <name>yarn.resourcemanager.ha.rm-ids</name>
        <value>rm1,rm2</value>
    </property>
    <property>
        <!-- RM1 的服務(wù)地址 -->
        <name>yarn.resourcemanager.hostname.rm1</name>
        <value>hadoop002</value>
    </property>
    <property>
        <!-- RM2 的服務(wù)地址 -->
        <name>yarn.resourcemanager.hostname.rm2</name>
        <value>hadoop003</value>
    </property>
    <property>
        <!-- RM1 Web 應(yīng)用程序的地址 -->
        <name>yarn.resourcemanager.webapp.address.rm1</name>
        <value>hadoop002:8088</value>
    </property>
    <property>
        <!-- RM2 Web 應(yīng)用程序的地址 -->
        <name>yarn.resourcemanager.webapp.address.rm2</name>
        <value>hadoop003:8088</value>
    </property>
    <property>
        <!-- ZooKeeper 集群的地址 -->
        <name>yarn.resourcemanager.zk-address</name>
        <value>hadoop001:2181,hadoop002:2181,hadoop003:2181</value>
    </property>
    <property>
        <!-- 啟用自動恢復(fù) -->
        <name>yarn.resourcemanager.recovery.enabled</name>
        <value>true</value>
    </property>
    <property>
        <!-- 用于進行持久化存儲的類 -->
        <name>yarn.resourcemanager.store.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
    </property>
</configuration>

5. mapred-site.xml

<configuration>
    <property>
        <!--指定 mapreduce 作業(yè)運行在 yarn 上-->
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
</configuration>

5. slaves

配置所有從屬節(jié)點的主機名或 IP 地址,每行一個乳乌。所有從屬節(jié)點上的 DataNode 服務(wù)和 NodeManager 服務(wù)都會被啟動捧韵。

hadoop001
hadoop002
hadoop003

4.4 分發(fā)程序

將 Hadoop 安裝包分發(fā)到其他兩臺服務(wù)器,分發(fā)后建議在這兩臺服務(wù)器上也配置一下 Hadoop 的環(huán)境變量汉操。

# 將安裝包分發(fā)到hadoop002
scp -r /usr/app/hadoop-2.6.0-cdh5.15.2/  hadoop002:/usr/app/
# 將安裝包分發(fā)到hadoop003
scp -r /usr/app/hadoop-2.6.0-cdh5.15.2/  hadoop003:/usr/app/

五再来、啟動集群

5.1 啟動ZooKeeper

分別到三臺服務(wù)器上啟動 ZooKeeper 服務(wù):

 zkServer.sh start

5.2 啟動Journalnode

分別到三臺服務(wù)器的的 ${HADOOP_HOME}/sbin 目錄下,啟動 journalnode 進程:

hadoop-daemon.sh start journalnode

5.3 初始化NameNode

hadop001 上執(zhí)行 NameNode 初始化命令:

hdfs namenode -format

執(zhí)行初始化命令后磷瘤,需要將 NameNode 元數(shù)據(jù)目錄的內(nèi)容芒篷,復(fù)制到其他未格式化的 NameNode 上。元數(shù)據(jù)存儲目錄就是我們在 hdfs-site.xml 中使用 dfs.namenode.name.dir 屬性指定的目錄采缚。這里我們需要將其復(fù)制到 hadoop002 上:

 scp -r /home/hadoop/namenode/data hadoop002:/home/hadoop/namenode/

5.4 初始化HA狀態(tài)

在任意一臺 NameNode 上使用以下命令來初始化 ZooKeeper 中的 HA 狀態(tài):

hdfs zkfc -formatZK

5.5 啟動HDFS

進入到 hadoop001${HADOOP_HOME}/sbin 目錄下针炉,啟動 HDFS。此時 hadoop001hadoop002 上的 NameNode 服務(wù)扳抽,和三臺服務(wù)器上的 DataNode 服務(wù)都會被啟動:

start-dfs.sh

5.6 啟動YARN

進入到 hadoop002${HADOOP_HOME}/sbin 目錄下篡帕,啟動 YARN。此時 hadoop002 上的 ResourceManager 服務(wù)贸呢,和三臺服務(wù)器上的 NodeManager 服務(wù)都會被啟動:

start-yarn.sh

需要注意的是镰烧,這個時候 hadoop003 上的 ResourceManager 服務(wù)通常是沒有啟動的,需要手動啟動:

yarn-daemon.sh start resourcemanager

六楞陷、查看集群

6.1 查看進程

成功啟動后怔鳖,每臺服務(wù)器上的進程應(yīng)該如下:

[root@hadoop001 sbin]# jps
4512 DFSZKFailoverController
3714 JournalNode
4114 NameNode
3668 QuorumPeerMain
5012 DataNode
4639 NodeManager


[root@hadoop002 sbin]# jps
4499 ResourceManager
4595 NodeManager
3465 QuorumPeerMain
3705 NameNode
3915 DFSZKFailoverController
5211 DataNode
3533 JournalNode


[root@hadoop003 sbin]# jps
3491 JournalNode
3942 NodeManager
4102 ResourceManager
4201 DataNode
3435 QuorumPeerMain

6.2 查看Web UI

HDFS 和 YARN 的端口號分別為 500708080,界面應(yīng)該如下:

此時 hadoop001 上的 NameNode 處于可用狀態(tài):

https://github.com/heibaiying

而 hadoop002 上的 NameNode 則處于備用狀態(tài):


https://github.com/heibaiying


hadoop002 上的 ResourceManager 處于可用狀態(tài):


https://github.com/heibaiying


hadoop003 上的 ResourceManager 則處于備用狀態(tài):


https://github.com/heibaiying


同時界面上也有 Journal Manager 的相關(guān)信息:


https://github.com/heibaiying

七固蛾、集群的二次啟動

上面的集群初次啟動涉及到一些必要初始化操作结执,所以過程略顯繁瑣。但是集群一旦搭建好后艾凯,想要再次啟用它是比較方便的昌犹,步驟如下(首選需要確保 ZooKeeper 集群已經(jīng)啟動):

hadoop001 啟動 HDFS,此時會啟動所有與 HDFS 高可用相關(guān)的服務(wù)览芳,包括 NameNode,DataNode 和 JournalNode:

start-dfs.sh

hadoop002 啟動 YARN:

start-yarn.sh

這個時候 hadoop003 上的 ResourceManager 服務(wù)通常還是沒有啟動的鸿竖,需要手動啟動:

yarn-daemon.sh start resourcemanager

參考資料

以上搭建步驟主要參考自官方文檔:

關(guān)于 Hadoop 高可用原理的詳細分析沧竟,推薦閱讀:

Hadoop NameNode 高可用 (High Availability) 實現(xiàn)解析

更多大數(shù)據(jù)系列文章可以參見 GitHub 開源項目大數(shù)據(jù)入門指南

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铸敏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子悟泵,更是在濱河造成了極大的恐慌杈笔,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糕非,死亡現(xiàn)場離奇詭異蒙具,居然都是意外死亡,警方通過查閱死者的電腦和手機朽肥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門禁筏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人衡招,你說我怎么就攤上這事篱昔。” “怎么了始腾?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵州刽,是天一觀的道長。 經(jīng)常有香客問我浪箭,道長穗椅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任奶栖,我火速辦了婚禮匹表,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驼抹。我一直安慰自己桑孩,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布框冀。 她就那樣靜靜地躺著流椒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪明也。 梳的紋絲不亂的頭發(fā)上宣虾,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音温数,去河邊找鬼绣硝。 笑死,一個胖子當(dāng)著我的面吹牛撑刺,可吹牛的內(nèi)容都是我干的鹉胖。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼甫菠!你這毒婦竟也來了挠铲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤寂诱,失蹤者是張志新(化名)和其女友劉穎拂苹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痰洒,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡瓢棒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了丘喻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脯宿。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖仓犬,靈堂內(nèi)的尸體忽然破棺而出嗅绰,到底是詐尸還是另有隱情,我是刑警寧澤搀继,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布窘面,位于F島的核電站,受9級特大地震影響叽躯,放射性物質(zhì)發(fā)生泄漏财边。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一点骑、第九天 我趴在偏房一處隱蔽的房頂上張望酣难。 院中可真熱鬧,春花似錦黑滴、人聲如沸憨募。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽菜谣。三九已至,卻和暖如春晚缩,著一層夾襖步出監(jiān)牢的瞬間尾膊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工荞彼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留冈敛,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓鸣皂,卻偏偏與公主長得像抓谴,于是被迫代替她去往敵國和親暮蹂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容