Hadoop 2.0 NameNode HA和Federation實(shí)踐
為什么需要HA和Federation
單點(diǎn)故障
在Hadoop 2.0之前,也有若干技術(shù)試圖解決單點(diǎn)故障的問題,我們在這里做個(gè)簡短的總結(jié)
1.Secondary NameNode。它不是HA,它只是階段性的合并edits和fsimage,以縮短集群啟動(dòng)的時(shí)間。當(dāng)NameNode(以下簡稱NN)失效的時(shí)候,Secondary NN并無法立刻提供服務(wù),Secondary NN甚至無法保證數(shù)據(jù)完整性:如果NN數(shù)據(jù)丟失的話,在上一次合并后的文件系統(tǒng)的改動(dòng)會(huì)丟失。
2.Backup NameNode (HADOOP-4539)。它在內(nèi)存中復(fù)制了NN的當(dāng)前狀態(tài),算是Warm Standby,可也就僅限于此,并沒有failover等。它同樣是階段性的做checkpoint,也無法保證數(shù)據(jù)完整性。手動(dòng)把name.dir指向NFS。這是安全的Cold Standby,可以保證元數(shù)據(jù)不丟失,但集群的恢復(fù)則完全靠手動(dòng)。
3.Facebook AvatarNode。Facebook有強(qiáng)大的運(yùn)維做后盾,所以Avatarnode只是Hot Standby,并沒有自動(dòng)切換,當(dāng)主NN失效的時(shí)候,需要管理員確認(rèn),然后手動(dòng)把對外提供服務(wù)的虛擬IP映射到Standby NN,這樣做的好處是確保不會(huì)發(fā)生腦裂的場景。其某些設(shè)計(jì)思想和Hadoop 2.0里的HA非常相似,從時(shí)間上來看,Hadoop 2.0應(yīng)該是借鑒了Facebook的做法。
4.還有若干解決方案,基本都是依賴外部的HA機(jī)制,譬如DRBD,Linux HA,VMware的FT等等。
集群容量和集群性能
單NN的架構(gòu)使得HDFS在集群擴(kuò)展性和性能上都有潛在的問題,當(dāng)集群大到一定程度后,NN進(jìn)程使用的內(nèi)存可能會(huì)達(dá)到上百G,常用的估算公式為1G對應(yīng)1百萬個(gè)塊,按缺省塊大小計(jì)算的話,大概是64T (這個(gè)估算比例是有比較大的富裕的,其實(shí),即使是每個(gè)文件只有一個(gè)塊,所有元數(shù)據(jù)信息也不會(huì)有1KB/block)。同時(shí),所有的元數(shù)據(jù)信息的讀取和操作都需要與NN進(jìn)行通信,譬如客戶端的addBlock、getBlockLocations,還有DataNode的blockRecieved、sendHeartbeat、blockReport,在集群規(guī)模變大后,NN成為了性能的瓶頸。Hadoop 2.0里的HDFS Federation就是為了解決這兩個(gè)問題而開發(fā)的。
Hadoop 2.0里HA的實(shí)現(xiàn)方式
圖片來源: HDFS-1623 設(shè)計(jì)文檔
圖片作者: Sanjay Radia, Suresh Srinivas
在這個(gè)圖里,我們可以看出HA的大致架構(gòu),其設(shè)計(jì)上的考慮包括:
利用共享存儲來在兩個(gè)NN間同步edits信息。
以前的HDFS是share nothing but NN,現(xiàn)在NN又share storage,這樣其實(shí)是轉(zhuǎn)移了單點(diǎn)故障的位置,但中高端的存儲設(shè)備內(nèi)部都有各種RAID以及冗余硬件包括電源以及網(wǎng)卡等,比服務(wù)器的可靠性還是略有提高。通過NN內(nèi)部每次元數(shù)據(jù)變動(dòng)后的flush操作,加上NFS的close-to-open,數(shù)據(jù)的一致性得到了保證。社區(qū)現(xiàn)在也試圖把元數(shù)據(jù)存儲放到BookKeeper上,以去除對共享存儲的依賴,Cloudera也提供了Quorum Journal Manager的實(shí)現(xiàn)和代碼,這篇中文的blog有詳盡分析:基于QJM/Qurom Journal Manager/Paxos的HDFS HA原理及代碼分析
DataNode(以下簡稱DN)同時(shí)向兩個(gè)NN匯報(bào)塊信息。
這是讓Standby NN保持集群最新狀態(tài)的必需步驟,不贅述。
用于監(jiān)視和控制NN進(jìn)程的FailoverController進(jìn)程
顯然,我們不能在NN進(jìn)程內(nèi)進(jìn)行心跳等信息同步,最簡單的原因,一次FullGC就可以讓NN掛起十幾分鐘,所以,必須要有一個(gè)獨(dú)立的短小精悍的watchdog來專門負(fù)責(zé)監(jiān)控。這也是一個(gè)松耦合的設(shè)計(jì),便于擴(kuò)展或更改,目前版本里是用ZooKeeper(以下簡稱ZK)來做同步鎖,但用戶可以方便的把這個(gè)ZooKeeper FailoverController(以下簡稱ZKFC)替換為其他的HA方案或leader選舉方案。
隔離(Fencing),防止腦裂,就是保證在任何時(shí)候只有一個(gè)主NN,包括三個(gè)方面:
共享存儲fencing,確保只有一個(gè)NN可以寫入edits。
客戶端fencing,確保只有一個(gè)NN可以響應(yīng)客戶端的請求。
DataNode fencing,確保只有一個(gè)NN可以向DN下發(fā)命令,譬如刪除塊,復(fù)制塊,等等。
Hadoop 2.0里Federation的實(shí)現(xiàn)方式
圖片來源: HDFS-1052 設(shè)計(jì)文檔
圖片作者: Sanjay Radia, Suresh Srinivas
這個(gè)圖過于簡明,許多設(shè)計(jì)上的考慮并不那么直觀,我們稍微總結(jié)一下
多個(gè)NN共用一個(gè)集群里DN上的存儲資源,每個(gè)NN都可以單獨(dú)對外提供服務(wù)
每個(gè)NN都會(huì)定義一個(gè)存儲池,有單獨(dú)的id,每個(gè)DN都為所有存儲池提供存儲
DN會(huì)按照存儲池id向其對應(yīng)的NN匯報(bào)塊信息,同時(shí),DN會(huì)向所有NN匯報(bào)本地存儲可用資源情況
如果需要在客戶端方便的訪問若干個(gè)NN上的資源,可以使用客戶端掛載表,把不同的目錄映射到不同的NN,但NN上必須存在相應(yīng)的目錄
這樣設(shè)計(jì)的好處大致有:
改動(dòng)最小,向前兼容
現(xiàn)有的NN無需任何配置改動(dòng).
如果現(xiàn)有的客戶端只連某臺NN的話,代碼和配置也無需改動(dòng)。
分離命名空間管理和塊存儲管理
提供良好擴(kuò)展性的同時(shí)允許其他文件系統(tǒng)或應(yīng)用直接使用塊存儲池
統(tǒng)一的塊存儲管理保證了資源利用率
可以只通過防火墻配置達(dá)到一定的文件訪問隔離,而無需使用復(fù)雜的Kerberos認(rèn)證
客戶端掛載表
通過路徑自動(dòng)對應(yīng)NN
使Federation的配置改動(dòng)對應(yīng)用透明
測試環(huán)境
以上是HA和Federation的簡介,對于已經(jīng)比較熟悉HDFS的朋友,這些信息應(yīng)該已經(jīng)可以幫助你快速理解其架構(gòu)和實(shí)現(xiàn),如果還需要深入了解細(xì)節(jié)的話,可以去詳細(xì)閱讀設(shè)計(jì)文檔或是代碼。這篇文章的主要目的是總結(jié)我們的測試結(jié)果,所以現(xiàn)在才算是正文開始。
為了徹底搞清HA和Federation的配置,我們直接一步到位,選擇了如下的測試場景,結(jié)合了HA和Federation:
這張圖里有個(gè)概念是前面沒有說明的,就是NameService。Hadoop 2.0里對NN進(jìn)行了一層抽象,提供服務(wù)的不再是NN本身,而是NameService(以下簡稱NS)。Federation是由多個(gè)NS組成的,每個(gè)NS又是由一個(gè)或兩個(gè)(HA)NN組成的。在接下里的測試配置里會(huì)有更直觀的例子。
圖中DN-1到DN-6是六個(gè)DataNode,NN-1到NN-4是四個(gè)NameNode,分別組成兩個(gè)HA的NS,再通過Federation組合對外提供服務(wù)。Storage Pool 1和Storage Pool 2分別對應(yīng)這兩個(gè)NS。我們在客戶端進(jìn)行了掛載表的映射,把/share映射到NS1,把/user映射到NS2,這個(gè)映射其實(shí)不光是要指定NS,還需要指定到其上的某個(gè)目錄,稍后的配置中大家可以看到。
下面我們來看看配置文件里需要做哪些改動(dòng),為了便于理解,我們先把HA和Federation分別介紹,然后再介紹同時(shí)使用HA和Federation時(shí)的配置方式,首先我們來看HA的配置:
對于HA中的所有節(jié)點(diǎn),包括NN和DN和客戶端,需要做如下更改:
HA,所有節(jié)點(diǎn),hdfs-site.xml
- <property>
- <name>dfs.nameservices</name>
- <value>ns1</value>
- <description>提供服務(wù)的NS邏輯名稱,與core-site.xml里的對應(yīng)</description>
- </property>
- <property>
- <name>dfs.ha.namenodes.${NS_ID}</name>
- <value>nn1,nn3</value>
- <description>列出該邏輯名稱下的NameNode邏輯名稱</description>
- </property>
- <property>
- <name>dfs.namenode.rpc-address.${NS_ID}.${NN_ID}</name>
- <value>host-nn1:9000</value>
- <description>指定NameNode的RPC位置</description>
- </property>
- <property>
- <name>dfs.namenode.http-address.${NS_ID}.${NN_ID}</name>
- <value>host-nn1:50070</value>
- <description>指定NameNode的Web Server位置</description>
- </property>
以上的示例里,我們用了${}來表示變量值,其展開后的內(nèi)容大致如下:
- <property>
- <name>dfs.ha.namenodes.ns1</name>
- <value>nn1,nn3</value>
- </property>
- <property>
- <name>dfs.namenode.rpc-address.ns1.nn1</name>
- <value>host-nn1:9000</value>
- </property>
- <property>
- <name>dfs.namenode.http-address.ns1.nn1</name>
- <value>host-nn1:50070</value>
- </property>
- <property>
- <name>dfs.namenode.rpc-address.ns1.nn3</name>
- <value>host-nn3:9000</value>
- </property>
- <property>
- <name>dfs.namenode.http-address.ns1.nn3</name>
- <value>host-nn3:50070</value>
- </property>
與此同時(shí),在HA集群的NameNode或客戶端還需要做如下配置的改動(dòng):
HA,NameNode,hdfs-site.xml
- <property>
- <name>dfs.namenode.shared.edits.dir</name>
- <value>file:///nfs/ha-edits</value>
- <description>指定用于HA存放edits的共享存儲,通常是NFS掛載點(diǎn)</description>
- </property>
- <property>
- <name>ha.zookeeper.quorum</name>
- <value>host-zk1:2181,host-zk2:2181,host-zk3:2181,</value>
- <description>指定用于HA的ZooKeeper集群機(jī)器列表</description>
- </property>
- <property>
- <name>ha.zookeeper.session-timeout.ms</name>
- <value>5000</value>
- <description>指定ZooKeeper超時(shí)間隔,單位毫秒</description>
- </property>
- <property>
- <name>dfs.ha.fencing.methods</name>
- <value>sshfence</value>
- <description>指定HA做隔離的方法,缺省是ssh,可設(shè)為shell,稍后詳述</description>
- </property>
HA,客戶端,hdfs-site.xml
- <property>
- <name>dfs.ha.automatic-failover.enabled</name>
- <value>true</value>
- <description>或者false</description>
- </property>
- <property>
- <name>dfs.client.failover.proxy.provider.${NS_ID}</name>
- <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
- <description>指定客戶端用于HA切換的代理類,不同的NS可以用不同的代理類
- 以上示例為Hadoop 2.0自帶的缺省代理類</description>
- </property>
最后,為了方便使用相對路徑,而不是每次都使用hdfs://ns1作為文件路徑的前綴,我們還需要在各角色節(jié)點(diǎn)上修改core-site.xml:
HA,所有節(jié)點(diǎn),core-site.xml
- <property>
- <name>fs.defaultFS</name>
- <value>hdfs://ns1</value>
- <description>缺省文件服務(wù)的協(xié)議和NS邏輯名稱,和hdfs-site里的對應(yīng)
- 此配置替代了1.0里的fs.default.name</description>
- </property>
接下來我們看一下如果單獨(dú)使用Federation,應(yīng)該如何配置,這里我們假設(shè)沒有使用HA,而是直接使用nn1和nn2組成了Federation集群,他們對應(yīng)的NS的邏輯名稱分別是ns1和ns2。為了便于理解,我們從客戶端使用的core-site.xml和掛載表入手:
Federation,所有節(jié)點(diǎn),core-site.xml
- <xi:include href=“cmt.xml"/>
- <property>
- <name>fs.defaultFS</name>
- <value>viewfs://nsX</value>
- <description>整個(gè)Federation集群對外提供服務(wù)的NS邏輯名稱,
- 注意,這里的協(xié)議不再是hdfs,而是新引入的viewfs
- 這個(gè)邏輯名稱會(huì)在下面的掛載表中用到</description>
- </property>
我們在上面的core-site中包含了一個(gè)cmt.xml文件,也就是Client Mount Table,客戶端掛載表,其內(nèi)容就是虛擬路徑到具體某個(gè)NS及其物理子目錄的映射關(guān)系,譬如/share映射到ns1的/real_share,/user映射到ns2的/real_user,示例如下:
Federation,所有節(jié)點(diǎn),cmt.xml
- <configuration>
- <property>
- <name>fs.viewfs.mounttable.nsX.link./share</name>
- <value>hdfs://ns1/real_share</value>
- </property>
- <property>
- <name>fs.viewfs.mounttable.nsX.link./user</name>
- <value>hdfs://ns2/real_user</value>
- </property>
- </configuration>
注意,這里面的nsX與core-site.xml中的nsX對應(yīng)。而且對每個(gè)NS,你都可以建立多個(gè)虛擬路徑,映射到不同的物理路徑。與此同時(shí),hdfs-site.xml中需要給出每個(gè)NS的具體信息:
Federation,所有節(jié)點(diǎn),hdfs-site.xml
- <property>
- <name>dfs.nameservices</name>
- <value>ns1,ns2</value>
- <description>提供服務(wù)的NS邏輯名稱,與core-site.xml或cmt.xml里的對應(yīng)</description>
- </property>
- <property>
- <name>dfs.namenode.rpc-address.ns1</name>
- <value>host-nn1:9000</value>
- </property>
- <property>
- <name>dfs.namenode.http-address.ns1</name>
- <value>host-nn1:50070</value>
- </property>
- <property>
- <name>dfs.namenode.rpc-address.ns2</name>
- <value>host-nn2:9000</value>
- </property>
- <property>
- <name>dfs.namenode.http-address.ns2</name>
- <value>host-nn2:50070</value>
- </property>
可以看到,在只有Federation且沒有HA的情況下,配置的name里只需要直接給出${NS_ID},然后value就是實(shí)際的機(jī)器名和端口號,不需要再.${NN_ID}。
這里有一個(gè)情況,就是NN本身的配置。從上面的內(nèi)容里大家可以知道,NN上是需要事先建立好客戶端掛載表映射的目標(biāo)物理路徑,譬如/real_share,之后才能通過以上的映射進(jìn)行訪問,可是,如果不指定全路徑,而是通過映射+相對路徑的話,客戶端只能在掛載點(diǎn)的虛擬目錄之下進(jìn)行操作,從而無法創(chuàng)建映射目錄本身的物理目錄。所以,為了在NN上建立掛載點(diǎn)映射目錄,我們就必須在命令行里使用hdfs協(xié)議和絕對路徑:
hdfs dfs -mkdir hdfs://ns1/real_share
上面這個(gè)問題,我在EasyHadoop的聚會(huì)上沒有講清楚,只是簡單的說在NN上不要使用viewfs://來配置,而是使用hdfs://,那樣是可以解決問題,但是是并不是最好的方案,也沒有把問題的根本說清楚。
最后,我們來組合HA和Federation,真正搭建出和本節(jié)開始處的測試環(huán)境示意圖一樣的實(shí)例。通過前面的描述,有經(jīng)驗(yàn)的朋友應(yīng)該已經(jīng)猜到了,其實(shí)HA+Federation配置的關(guān)鍵,就是組合hdfs-site.xml里的dfs.nameservices以及dfs.ha.namenodes.${NS_ID},然后按照${NS_ID}和${NN_ID}來組合name,列出所有NN的信息即可。其余配置一樣。
HA + Federation,所有節(jié)點(diǎn),hdfs-site.xml
- <property>
- <name>dfs.nameservices</name>
- <value>ns1, ns2</value>
- </property>
- <property>
- <name>dfs.ha.namenodes.ns1</name>
- <value>nn1,nn3</value>
- </property>
- <property>
- <name>dfs.ha.namenodes.ns2</name>
- <value>nn2,nn4</value>
- </property>
- <property>
- <name>dfs.namenode.rpc-address.ns1.nn1</name>
- <value>host-nn1:9000</value>
- </property>
- <property>
- <name>dfs.namenode.http-address.ns1.nn1</name>
- <value>host-nn1:50070</value>
- </property>
- <property>
- <name>dfs.namenode.rpc-address.ns1.nn3</name>
- <value>host-nn3:9000</value>
- </property>
- <property>
- <name>dfs.namenode.http-address.ns1.nn3</name>
- <value>host-nn3:50070</value>
- </property>
- <property>
- <name>dfs.namenode.rpc-address.ns2.nn2</name>
- <value>host-nn2:9000</value>
- </property>
- <property>
- <name>dfs.namenode.http-address.ns2.nn2</name>
- <value>host-nn2:50070</value>
- </property>
- <property>
- <name>dfs.namenode.rpc-address.ns2.nn4</name>
- <value>host-nn4:9000</value>
- </property>
- <property>
- <name>dfs.namenode.http-address.ns2.nn4</name>
- <value>host-nn4:50070</value>
- </property>
對于沒有.${NS_ID},也就是未區(qū)分NS的項(xiàng)目,需要在每臺NN上分別使用不同的值單獨(dú)配置,尤其是NFS位置(dfs.namenode.shared.edits.dir),因?yàn)椴煌琋S必定要使用不同的NFS目錄來做各自內(nèi)部的HA (除非mount到本地是相同的,只是在NFS服務(wù)器端是不同的,但這樣是非常不好的實(shí)踐);而像ZK位置和隔離方式等其實(shí)大可使用一樣的配置。
除了配置以外,集群的初始化也有一些額外的步驟,譬如,創(chuàng)建HA環(huán)境的時(shí)候,需要先格式化一臺NN,然后同步其name.dir下面的數(shù)據(jù)到第二臺,然后再啟動(dòng)集群 (我們沒有測試從單臺升級為HA的情況,但道理應(yīng)該一樣)。在創(chuàng)建Federation環(huán)境的時(shí)候,需要注意保持${CLUSTER_ID}的值,以確保所有NN能共享同一個(gè)集群的存儲資源,具體做法是在格式化第一臺NN之后,取得其${CLUSTER_ID}的值,然后用如下命令格式化其他NN:
hadoop namenode -format -clusterid ${CLUSTER_ID}
當(dāng)然,你也可以從第一臺開始就使用自己定義的${CLUSTER_ID}值。
如果是HA + Federation的場景,則需要用Federation的格式化方式初始化兩臺,每個(gè)HA環(huán)境一臺,保證${CLUSTER_ID}一致,然后分別同步name.dir下的元數(shù)據(jù)到HA環(huán)境里的另一臺上,再啟動(dòng)集群。
Hadoop 2.0中的HDFS客戶端和API也有些許更改,命令行引入了新的hdfs命令,hdfs dfs就等同于以前的hadoop fs命令。API里引入了新的ViewFileSystem類,可以通過它來獲取掛載表的內(nèi)容,如果你不需要讀取掛載表內(nèi)容,而只是使用文件系統(tǒng)的話,可以無視掛載表,直接通過路徑來打開或創(chuàng)建文件。代碼示例如下:
- ViewFileSystem fsView = (ViewFileSystem) ViewFileSystem.get(conf);
- MountPoint[] m = fsView.getMountPoints();
- for (MountPoint m1 : m)
- System.out.println( m1.getSrc() );
- // 直接使用/share/test.txt創(chuàng)建文件
- // 如果按照之前的配置,客戶端會(huì)自動(dòng)根據(jù)掛載表找到是ns1
- // 然后再通過failover proxy類知道nn1是Active NN并與其通信
- Path p = new Path("/share/test.txt");
- FSDataOutputStream fos = fsView.create(p);
HA測試方案和結(jié)果
Federation的測試主要是功能性上的,能用就OK了,這里的測試方案只是針對HA而言。我們設(shè)計(jì)了兩個(gè)維度的測試矩陣:系統(tǒng)失效方式,客戶端連接模型
系統(tǒng)失效有兩種:
1.終止NameNode進(jìn)程:ZKFC主動(dòng)釋放鎖
模擬機(jī)器OOM、死鎖、硬件性能驟降等故障
2.NN機(jī)器掉電:ZK鎖超時(shí)
模擬網(wǎng)絡(luò)和交換機(jī)故障、以及掉電本身
客戶端連接也是兩種:
1.已連接的客戶端(持續(xù)拷貝96M的文件,1M每塊)
通過增加塊的數(shù)目,我們希望客戶端會(huì)不斷的向NN去申請新的塊;一般是在第一個(gè)文件快結(jié)束或第二個(gè)文件剛開始拷貝的時(shí)候使系統(tǒng)失效。
2.新發(fā)起連接的客戶端(持續(xù)拷貝96M的文件,100M每塊)
因?yàn)橹挥幸粋€(gè)塊,所以在實(shí)際拷貝過程中失效并不會(huì)立刻導(dǎo)致客戶端或DN報(bào)錯(cuò),但下一次新發(fā)起連接的客戶端會(huì)一開始就沒有NN可連;一般是在第一個(gè)文件快結(jié)束拷貝時(shí)使系統(tǒng)失效。
針對每一種組合,我們反復(fù)測試10-30次,每次拷貝5個(gè)文件進(jìn)入HDFS,因?yàn)闀r(shí)間不一定掐的很準(zhǔn),所以有時(shí)候也會(huì)是在第三或第四個(gè)文件的時(shí)候才使系統(tǒng)失效,不管如何,我們會(huì)在結(jié)束后從HDFS里取出所有文件,并挨個(gè)檢查文件MD5,以確保數(shù)據(jù)的完整性。
測試結(jié)果如下:
ZKFC主動(dòng)釋放鎖
5-8秒切換(需同步edits)
客戶端偶爾會(huì)有重試(~10%)
但從未失敗
ZK鎖超時(shí)
15-20s切換(超時(shí)設(shè)置為10s)
客戶端重試幾率變大(~75%)
且偶有失敗(~15%),但僅見于已連接客戶端
可確保數(shù)據(jù)完整性
MD5校驗(yàn)從未出錯(cuò)
失敗時(shí)客戶端有Exception
我們的結(jié)論是:Hadoop 2.0里的HDFS HA基本可滿足高可用性
擴(kuò)展測試
我們另外還(試圖)測試Append時(shí)候NN失效的情形,因?yàn)锳ppend的代碼邏輯非常復(fù)雜,所以期望可以有新的發(fā)現(xiàn),但是由于復(fù)雜的那一段只是在補(bǔ)足最尾部塊的時(shí)候,所以必須在測試程序一運(yùn)行起來就關(guān)掉NN,測了幾次,沒發(fā)現(xiàn)異常情況。另外我們還使用HBase進(jìn)行了測試,由于WAL只是append,而且HFile的compaction操作又并不頻繁,所以也沒有遇到問題。
HA推薦配置及其他
HA推薦配置
ha.zookeeper.session-timeout.ms = 10000
ZK心跳是2000
缺省的5000很容易因?yàn)榫W(wǎng)絡(luò)擁塞或NN GC等導(dǎo)致誤判
為避免電源閃斷,不要把start-dfs.sh放在init.d里
dfs.ha.fencing.methods = shell(/path/to/the/script)
STONITH (Shoot The Other Node In The Head)不一定可行,當(dāng)沒有網(wǎng)絡(luò)或掉電的時(shí)候,是沒法shoot的
缺省的隔離手段是sshfence,在掉電情況下就無法成功完成,從而切換失敗
唯一能保證不發(fā)生腦裂的方案就是確保原Active無法訪問NFS
通過script修改NFS上的iptables,禁止另一臺NN訪問
管理員及時(shí)介入,恢復(fù)原Active,使其成為Standby?;謴?fù)iptables
客戶端重試機(jī)制
代碼可在org.apache.hadoop.io.retry.RetryPolicies.FailoverOnNetworkExceptionRetry里找到。目前的客戶端在遇到以下Exception時(shí)啟動(dòng)重試:
- // 連接失敗
- ConnectException
- NoRouteToHostException
- UnKnownHostException
- // 連到了Standby而不是Active
- StandbyException
其重試時(shí)間間隔的計(jì)算公式為:
RAND(0.5~1.5) * min (2^retryies * baseMillis, maxMillis)
baseMillis = dfs.client.failover.sleep.base.millis,缺省500
maxMillis = dfs.client.failover.sleep.max.millis,缺省15000
最大重試次數(shù):dfs.client.failover.max.attempts,缺省15
未盡事宜
關(guān)于那15%失敗的情況,我們從日志和代碼分析,基本確認(rèn)是HA里的問題,就是Standby NN在變?yōu)锳ctive NN的過程中,會(huì)試圖重置文件的lease的owner,從而導(dǎo)致LeaseExpiredException: Lease mismatch,客戶端遇到這個(gè)異常不會(huì)重試,導(dǎo)致操作失敗。這是一個(gè)非常容易重現(xiàn)的問題,相信作者也知道,可能是為了lease安全性也就是數(shù)據(jù)完整性做的一個(gè)取舍吧:寧可客戶端失敗千次,不可lease分配錯(cuò)一次,畢竟,客戶端失敗再重新創(chuàng)建文件是一個(gè)很廉價(jià)且安全的過程。另外,與MapReduce 2.0 (YARN)的整合測試我們也沒來得及做,原因是我們覺得YARN本身各個(gè)組件的HA還不完善,用它來測HDFS的HA有點(diǎn)本末倒置。
原文鏈接:http://www.sizeofvoid.net/hadoop-2-0-namenode-ha-federation-practice-zh/