這是我參與更文挑戰的第11天,活動詳情查看:更文挑戰html
高可用HA
概念
1、hadoop1.0的侷限
- namenode的問題
- 單點故障:只有一個namenode
- 單點瓶頸:一個namenode,可能內存不足以管理全部datanode
2、高可用(high availability)
- 用於解決單點故障
- hadoop2.0只支持2個節點的HA,3.0能夠一主多從
- 若是主節點(master)出現故障,就轉到備用節點(stand by)
- HA的架構

- HDFS的高可靠性(HA)主要體如今利用zookeeper實現主備NameNode,以解決單點NameNode故障問題。
- ZooKeeper主要用來存儲HA下的狀態文件,主備信息。 ZK個數建議3個及以上且爲奇數
個java
- NameNode主備模式,主提供服務,備同步主元數據並做爲主的熱備。
- ZKFC(ZooKeeper Failover Controller)用於監控NameNode節點的主備狀態。
- JN(JournalNode)用於存儲Active NameNode生成的Editlog。 Standby NameNode加載JN上Editlog,同步元數據。
- ZKFC控制NameNode主備仲裁
- ZKFC做爲一個精簡的仲裁代理,其利用zookeeper的分佈式鎖功能,實現主備仲裁,再經過命令通道,控制NameNode的主備狀態。 ZKFC與NN部署在一塊兒,二者個數相同。
- 元數據同步
- 兩個NN的數據同步:兩個namenode並非同時在工做,同時間只有一個NN在工做
- 兩個NN必須同步數據信息
- 塊位置信息(block imformation),它是由datanode處理的,而且要向NN彙報————動態數據信息
- 偏移量,大小,id,這些都是由NN本身來處理完成————靜態信息
- 動態信息的同步
- 由DN向NN彙報
- 由原來的DN向單一NN彙報變成向多個NN彙報
- 靜態信息的同步
- 既然靜態數據信息都由NN本身處理完成,那麼有兩個NN,要怎麼同步這兩個NN的信息呢?
- 把多個journalnode節點部署在不一樣的服務器上,其實每一個節點都是接收相同信息,多個節點就是爲了防止單點故障
- 主NN把數據往journalnode節點裏寫,備份NN從journalnode裏讀數據
- 過半機制(弱一致性):容許一小半的journalnode節點失效
- 主NN寫數據不必定要全部journalnode都肯定寫入完成,容許有一小半失效
- 通常會配置奇數個journalnode節點
- 好比3個容許1個失效,5個容許兩個失效
- 元數據持久化
- 主NameNode對外提供服務。生成的Editlog同時寫入本地和JN,同時更新主NameNode內存中的元數據。
- 備NameNode監控到JN上Editlog變化時,加載Editlog進內存,生成新的與主NameNode同樣的元數據。元數據同步完成。
- 主備的FSImage仍保存在各自的磁盤中,不發生交互。 FSImage是內存中元數據定時寫到本地磁盤的副本,也叫元數據鏡像

- EditLog:記錄用戶的操做日誌,用以在FSImage的基礎上生成新的文件系統鏡像。
- FSImage:用以階段性保存文件鏡像。
- FSImage.ckpt:在內存中對fsimage文件和EditLog文件合併(merge)後產生新的fsimage,寫到磁盤上,這個過程叫checkpoint.。備用NameNode加載完fsimage和EditLog文件後,會將merge後的結果同時寫到本地磁盤和NFS。此時磁盤上有一份原始的fsimage文件和一份新生成的checkpoint文件: fsimage.ckpt. 然後將fsimage.ckpt更名爲fsimage(覆蓋原有的fsimage)。
- EditLog.new: NameNode每隔1小時或Editlog滿64MB就觸發合併,合併時,將數據傳到Standby NameNode時,因數據讀寫不能同步進行,此時NameNode產生一個新的日誌文件Editlog.new用來存放這段時間的操做日誌。 Standby NameNode合併成fsimage後回傳給主NameNode替換掉原有fsimage,並將Editlog.new 命名爲Editlog。
- zookeeper集羣
- 主NN發生故障時,用於自動切換NN
- zookeeper會把zkfc進程部署在NN上,進行選舉和健康檢查,一旦發現NN掛掉了,就會通知stand by NN(注意,zookeeper只會監控狀態,切換主從都是NN本身決定的)
- 一旦主NN掛掉,它當即切換爲stand by,而另外一個NN自動切換爲active
3、聯邦(federation)
- 架構

- 產生緣由:單Active NN的架構使得HDFS在集羣擴展性和性能上都有潛在的問題,當集羣大到必定程度後, NN進程使用的內存可能會達到上百G, NN成爲了性能的瓶頸。
- 應用場景:超大規模文件存儲。如互聯網公司存儲用戶行爲數據、電信歷史數據、語音數據等超大規模數據存儲。此時NameNode的內存不足以支撐如此龐大的集羣。
- 經常使用的估算公式爲1G對應1百萬個塊,按缺省塊大小計算的話,大概是128T (這個估算比例是有比較大的富裕的,其實,即便是每一個文件只有一個塊,全部元數據信息也不會有1KB/block)。
- Federation簡單理解:各NameNode負責本身所屬的目錄。與Linux掛載磁盤到目錄相似,此時每一個NameNode只負責整個hdfs集羣中部分目錄。如NameNode1負責/database目錄,那麼在/database目錄下的文件元數據都由NameNode1負責。各NameNode間元數據不共享,每一個NameNode都有對應的standby。
- 塊池(block pool) :屬於某一命名空間(NS)的一組文件塊。
- 聯邦環境下,每一個namenode維護一個命名空間卷(namespace volume),包括命名空間的元數據和在該空間下的文件的全部數據塊的塊池。
- namenode之間是相互獨立的,兩兩之間並不互相通訊,一個失效也不會影響其餘namenode。
- datanode向集羣中全部namenode註冊,爲集羣中的全部塊池存儲數據。
- ameSpace(NS):命名空間。 HDFS的命名空間包含目錄、文件和塊。能夠理解爲NameNode所屬的邏輯目錄。
HA高可用搭建
1、各服務節點安裝位置

- ZK位置任意,必須先啓動(它要肯定主NN)
- ZKFC必須在NN上
- JNN位置任意
2、準備
- 實現node1和node2之間免密登陸
- 因爲node一、node2都爲NN,所以它們故障時須要切換,因此這兩個node之間要配置SSH免密
3、配置hdfs-site.xml
- dfs.nameservices - the logical name for this new nameservice
- 主節點服務id(這裏配置的是mycluser)
- 提供了惟一的一個名稱,指向須要作主從配置的兩個namenode節點
- 至關與是一個入口
- 這個名字只是表明一隊主從(hadoop2.0只能有兩個NN),若是要作聯邦,那麼能夠用逗號隔開不一樣的id名
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
複製代碼
- dfs.ha.namenodes.[nameservice ID] - unique identifiers for each NameNode in the nameservice
- 指定哪些NN是上面的id所屬的服務
- 能夠看出下面的nn1,nn2也是邏輯名
- 但能夠指出上面配置的nameservices指向哪些NN
- dfs.ha.namenodes.mycluster最後一個詞是上面的nameservices的id
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
複製代碼
- dfs.namenode.rpc-address.[nameservice ID].[name node ID] - the fully-qualified RPC(remote produce call) address for each NameNode to listen on
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
//物理機的ip地址
<value>node1:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>node2:8020</value>
</property>
複製代碼
- dfs.namenode.http-address.[nameservice ID].[name node ID] - the fully-qualified HTTP address for each NameNode to listen on
- 給瀏覽器提供服務,用瀏覽器訪問hadoop集羣
- 端口是50070
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>node1:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>node2:50070</value>
</property>
複製代碼
- dfs.namenode.shared.edits.dir - the URI which identifies the group of JNs where the NameNodes will write/read edits
- journalnode部署在哪些服務器上,對外通信的地址是什麼
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node2:8485;node3:8485;node4:8485/mycluster</value>
</property>
複製代碼
- dfs.client.failover.proxy.provider.[nameservice ID] - the Java class that HDFS clients use to contact the Active NameNode
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
複製代碼
- dfs.ha.fencing.methods - a list of scripts or Java classes which will be used to fence the Active NameNode during a failover
- 當一個NN發生故障的時候要當即把它隔離,不然會形成腦裂;而另外一個會當即變爲active
//採用ssh方式隔離
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_dsa</value>
</property>
複製代碼
- fs.defaultFS - the default path prefix used by the Hadoop FS client when none is given
- 配置在core-site.xml文件中
- 配置客戶端訪問HA的hasoop的邏輯路徑,使用以前的nameservice ID做爲hdfs path
<property>
<name>fs.defaultFS</name>
#注意這裏手打mycluster時千萬不要打成mycluser
<value>hdfs://mycluster</value>
</property>
//以前是下面這樣配置的,只有一個namenode,因此直接配置了哪一個NN的路徑,這裏使用服務id
<property>
<name>fs.defaultFS</name>
<value>hdfs://node1:9000</value>
</property>
//順便再作一個修改
//把NN和DN存儲數據位置的目錄再改變一下
<property>
<name>hadoop.tmp.dir</name>
<value>/var/hadoop/ha</value>
</property>
複製代碼
- dfs.journalnode.edits.dir - the path where the JournalNode daemon will store its local state
- journalnode產生的日誌存在節點的哪一個目錄下
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/var/hadoop/ha/journalnode</value>
</property>
複製代碼
4、配置zookeeper
- The configuration of automatic failover requires the addition of two new parameters to your configuration. In your
hdfs-site.xml
file, add:
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
複製代碼
- This specifies that the cluster should be set up for automatic failover. In your
core-site.xml
file, add:
<property>
<name>ha.zookeeper.quorum</name>
<value>node2:2181,node3:2181,node4:2181</value>
</property>
複製代碼
5、啓動前準備
- 把修改好的core-site.xml和hdfs-site.xml分發到其餘節點
6、zookeeper配置文件修改
- 打開zookeeper軟件的
/conf/zoo_sample.cfg
目錄
#1. 更名
mv zoo_sample.cfg zoo.cfg
#2. 配置文件修改
#autopurge.purgeInterval=1
#autopurge.purgeInterval=1
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
//這裏要修改,這個目錄不存在,要手動建立
dataDir=/var/hadoop/zk
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
//添加下面三行(有幾臺服務器參與,以繼通訊端口)
server.1=node2:2888:3888
server.2=node3:2888:3888
server.3=node4:2888:3888
複製代碼
- 添加幾個文件
- 上面修改了zookeeper配置文件,添加了路徑
/var/hadoop/zk
- 在每個要配置zookeeper服務的節點上都要在這個目錄的下面建立文件myid
//三臺服務器上
echo 1 >> /var/hadoop/zk/myid
echo 2 >> /var/hadoop/zk/myid
echo 3 >> /var/hadoop/zk/myid
複製代碼
- 配置zookeeper環境變量
7、執行
- 啓動zookeeper
- 啓動命令
zkServer.sh start
- 做用在node2,node3,node4
- 啓動後,狀態以下
[root@node4 hadoop]
7590 QuorumPeerMain
7607 Jps
複製代碼
[root@node4 conf]
JMX enabled by default
Using config: /opt/hadoop/zookeeper-3.4.6/bin/../conf/zoo.cfg
//說明這個節點是zookeeper集羣主節點
Mode: leader
複製代碼
- 啓動journalnode(第一次啓動集羣時執行,之後不用執行)
- 啓動命令:
hadoop-daemon.sh start journalnode
- 做用在node1,node2,node2
- 產生了一個新的進程
[root@node1 hadoop]
7912 Jps
7866 JournalNode
複製代碼
- 格式化hdfs(第一次啓動集羣時執行,之後不用執行)
- hdfs在zookeeper上註冊(第一次啓動集羣時執行,之後不用執行)
- hdfs在zookeeper上建立本身的節點
- 使用命令
hdfs zkfc -formatZK
- zookeeper能夠同時維護多個集羣的信息,因此這個命令的意思就是把這個集羣的信息格式化到zookeeper上
- zookeeper會建立一個
/hadoop-ha/mycluster
目錄在保存這個集羣的全部信息
- 啓動集羣
start-dfs.sh
- 要說明的是zkfc進程不須要手動啓動,它會隨集羣本身啓動
//node1
[root@node1 ~]
7185 Jps
6603 NameNode
7116 DFSZKFailoverController
6462 JournalNode
//node2
[root@node2 ~]
6945 Jps
6770 DataNode
6899 DFSZKFailoverController
6700 NameNode
6445 QuorumPeerMain
6494 JournalNode
//node3
[root@node3 ~]
6629 DataNode
6492 JournalNode
6718 Jps
6447 QuorumPeerMain
//node4
[root@node4 ~]
6454 QuorumPeerMain
6598 DataNode
6667 Jps
複製代碼