一、高可用簡介
hadoop 高可用 (high availability) 分為 hdfs 高可用和 yarn 高可用,兩者的實(shí)現(xiàn)基本類似,但 hdfs namenode 對數(shù)據(jù)存儲及其一致性的要求比 yarn resourcemanger 高得多,所以它的實(shí)現(xiàn)也更加復(fù)雜,故下面先進(jìn)行講解:
1.1 高可用整體架構(gòu)
hdfs 高可用架構(gòu)如下:

圖片引用自: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 作為獨(dú)立的進(jìn)程運(yùn)行,對 namenode 的主備切換進(jìn)行總體控制。zkfailovercontroller 能及時檢測到 namenode 的健康狀況,在主 namenode 故障時借助 zookeeper 實(shí)現(xiàn)自動的主備選舉和切換,當(dāng)然 namenode 目前也支持不依賴于 zookeeper 的手動主備切換。
- zookeeper 集群:為主備切換控制器提供主備選舉支持。
- 共享存儲系統(tǒng):共享存儲系統(tǒng)是實(shí)現(xiàn) namenode 的高可用最為關(guān)鍵的部分,共享存儲系統(tǒng)保存了 namenode 在運(yùn)行過程中所產(chǎn)生的 hdfs 的元數(shù)據(jù)。主 namenode 和 namenode 通過共享存儲系統(tǒng)實(shí)現(xiàn)元數(shù)據(jù)同步。在進(jìn)行主備切換的時候,新的主 namenode 在確認(rèn)元數(shù)據(jù)完全同步之后才能繼續(xù)對外提供服務(wù)。
- datanode 節(jié)點(diǎn):除了通過共享存儲系統(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ù)同步機(jī)制分析
目前 hadoop 支持使用 quorum journal manager (qjm) 或 network file system (nfs) 作為共享的存儲系統(tǒng),這里以 qjm 集群為例進(jìn)行說明:active namenode 首先把 editlog 提交到 journalnode 集群,然后 standby namenode 再從 journalnode 集群定時同步 editlog,當(dāng) active namenode 宕機(jī)后, standby namenode 在確認(rèn)元數(shù)據(jù)完全同步之后就可以對外提供服務(wù)。
需要說明的是向 journalnode 集群寫入 editlog 是遵循 “過半寫入則成功” 的策略,所以你至少要有3個 journalnode 節(jié)點(diǎn),當(dāng)然你也可以繼續(xù)增加節(jié)點(diǎn)數(shù)量,但是應(yīng)該保證節(jié)點(diǎn)總數(shù)是奇數(shù)。同時如果有 2n+1 臺 journalnode,那么根據(jù)過半寫的原則,最多可以容忍有 n 臺 journalnode 節(jié)點(diǎn)掛掉。

1.3 namenode 主備切換
namenode 實(shí)現(xiàn)主備切換的流程下圖所示:

-
healthmonitor 初始化完成之后會啟動內(nèi)部的線程來定時調(diào)用對應(yīng) namenode 的 haserviceprotocol rpc 接口的方法,對 namenode 的健康狀態(tài)進(jìn)行檢測。
-
healthmonitor 如果檢測到 namenode 的健康狀態(tài)發(fā)生變化,會回調(diào) zkfailovercontroller 注冊的相應(yīng)方法進(jìn)行處理。
-
如果 zkfailovercontroller 判斷需要進(jìn)行主備切換,會首先使用 activestandbyelector 來進(jìn)行自動的主備選舉。
-
activestandbyelector 與 zookeeper 進(jìn)行交互完成自動的主備選舉。
-
activestandbyelector 在主備選舉完成后,會回調(diào) zkfailovercontroller 的相應(yīng)方法來通知當(dāng)前的 namenode 成為主 namenode 或備 namenode。
-
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ù)信息需要維護(hù),所以它的狀態(tài)信息可以直接寫到 zookeeper 上,并依賴 zookeeper 來進(jìn)行主備選舉。

二、集群規(guī)劃
按照高可用的設(shè)計目標(biāo):需要保證至少有兩個 namenode (一主一備) 和 兩個 resourcemanager (一主一備) ,同時為滿足“過半寫入則成功”的原則,需要至少要有3個 journalnode 節(jié)點(diǎn)。這里使用三臺主機(jī)進(jìn)行搭建,集群規(guī)劃如下:

三、前置條件
- 所有服務(wù)器都安裝有jdk,安裝步驟可以參見:linux下jdk的安裝;
- 搭建好zookeeper集群,搭建步驟可以參見:zookeeper單機(jī)環(huán)境和集群環(huán)境搭建
- 所有服務(wù)器之間都配置好ssh免密登錄。
四、集群配置
4.1 下載并解壓
下載hadoop。這里我下載的是cdh版本hadoop,下載地址為:http://archive.cloudera.com/cdh5/cdh/5/
1
|
# tar -zvxf hadoop-2.6.0-cdh5.15.2.tar.gz |
4.2 配置環(huán)境變量
編輯profile
文件:
1
|
# vim /etc/profile |
增加如下配置:
1
2
|
export hadoop_home=/usr/app/hadoop-2.6.0-cdh5.15.2 export path=${hadoop_home}/bin:$path |
執(zhí)行source
命令,使得配置立即生效:
1
|
# source /etc/profile |
4.3 修改配置
進(jìn)入${hadoop_home}/etc/hadoop
目錄下,修改配置文件。各個配置文件內(nèi)容如下:
1. hadoop-env.sh
1
2
|
# 指定jdk的安裝位置 export java_home=/usr/java/jdk1.8.0_201/ |
2. core-site.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
<configuration> <property> <! -- 指定hdfs副本的數(shù)量 --> < name >dfs.replication</ name > <value>3</value> </property> <property> <! -- namenode節(jié)點(diǎn)數(shù)據(jù)(即元數(shù)據(jù))的存放位置,可以指定多個目錄實(shí)現(xiàn)容錯,多個目錄用逗號分隔 --> < name >dfs.namenode. name .dir</ name > <value>/home/hadoop/namenode/data</value> </property> <property> <! -- datanode節(jié)點(diǎn)數(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> <! -- 配置隔離機(jī)制,確保在任何給定時間只有一個namenode處于活動狀態(tài) --> < name >dfs.ha.fencing.methods</ name > <value>sshfence</value> </property> <property> <! -- 使用sshfence機(jī)制時需要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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<configuration> <property> <! --配置nodemanager上運(yùn)行的附屬服務(wù)。需要配置成mapreduce_shuffle后才可以在yarn上運(yùn)行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> <! -- 用于進(jìn)行持久化存儲的類 --> < name >yarn.resourcemanager.store.class</ name > <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.zkrmstatestore</value> </property> </configuration> |
5. mapred-site.xml
1
2
3
4
5
6
7
|
<configuration> <property> <! --指定mapreduce作業(yè)運(yùn)行在yarn上--> < name >mapreduce.framework. name </ name > <value>yarn</value> </property> </configuration> |
5. slaves
配置所有從屬節(jié)點(diǎn)的主機(jī)名或ip地址,每行一個。所有從屬節(jié)點(diǎn)上的datanode
服務(wù)和nodemanager
服務(wù)都會被啟動。
1
2
3
|
hadoop001 hadoop002 hadoop003 |
4.4 分發(fā)程序
將hadoop安裝包分發(fā)到其他兩臺服務(wù)器,分發(fā)后建議在這兩臺服務(wù)器上也配置一下hadoop的環(huán)境變量。
1
2
3
4
|
# 將安裝包分發(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ù):
1
|
zkserver.sh start |
5.2 啟動journalnode
分別到三臺服務(wù)器的的${hadoop_home}/sbin
目錄下,啟動journalnode
進(jìn)程:
1
|
hadoop-daemon.sh start journalnode |
5.3 初始化namenode
在hadop001
上執(zhí)行namenode
初始化命令:
1
|
hdfs namenode -format |
執(zhí)行初始化命令后,需要將namenode
元數(shù)據(jù)目錄的內(nèi)容,復(fù)制到其他未格式化的namenode
上。元數(shù)據(jù)存儲目錄就是我們在hdfs-site.xml
中使用dfs.namenode.name.dir
屬性指定的目錄。這里我們需要將其復(fù)制到hadoop002
上:
1
|
scp -r /home/hadoop/namenode/data hadoop002:/home/hadoop/namenode/ |
5.4 初始化ha狀態(tài)
在任意一臺namenode
上使用以下命令來初始化zookeeper中的ha狀態(tài):
1
|
hdfs zkfc -formatzk |
5.5 啟動hdfs
進(jìn)入到hadoop001
的${hadoop_home}/sbin
目錄下,啟動hdfs。此時hadoop001
和hadoop002
上的namenode
服務(wù),和三臺服務(wù)器上的datanode
服務(wù)都會被啟動:
1
|
start-dfs.sh |
5.6 啟動yarn
進(jìn)入到hadoop002
的${hadoop_home}/sbin
目錄下,啟動yarn。此時hadoop002
上的resourcemanager
服務(wù),和三臺服務(wù)器上的nodemanager
服務(wù)都會被啟動:
1
|
start-yarn.sh |
需要注意的是,這個時候hadoop003
上的resourcemanager
服務(wù)通常是沒有啟動的,需要手動啟動:
1
|
yarn-daemon.sh start resourcemanager |
六、查看集群
6.1 查看進(jìn)程
成功啟動后,每臺服務(wù)器上的進(jìn)程應(yīng)該如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
[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的端口號分別為50070
和8080
,界面應(yīng)該如下:
此時hadoop001上的namenode
處于可用狀態(tài):

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

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

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

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

七、集群的二次啟動
上面的集群初次啟動涉及到一些必要初始化操作,所以過程略顯繁瑣。但是集群一旦搭建好后,想要再次啟用它是比較方便的,步驟如下(首選需要確保zookeeper集群已經(jīng)啟動):
在hadoop001
啟動 hdfs,此時會啟動所有與 hdfs 高可用相關(guān)的服務(wù),包括 namenode,datanode 和 journalnode:
1
|
start-dfs.sh |
在hadoop002
啟動yarn:
1
|
start-yarn.sh |
這個時候hadoop003
上的resourcemanager
服務(wù)通常還是沒有啟動的,需要手動啟動:
1
|
yarn-daemon.sh start resourcemanager |
參考資料
以上搭建步驟主要參考自官方文檔:
總結(jié)
以上所述是小編給大家介紹的基于 ZooKeeper 搭建 高可用集群 的教程圖解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對服務(wù)器之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
原文鏈接:https://www.cnblogs.com/heibaiying/archive/2019/06/23/11071857.html