Hadoop集羣管理基礎知識筆記

1.Hadoop集羣儘量採用ECC內存,否則可能會出現校驗和錯誤,ECC內存有糾錯功能。在磁盤方面,儘管namenode建議採用RAID以保護元數據,但是將RAID用於datanode不會給HDFS帶來益處,速度依然比HDFS的JBOD(Just a Bunch Of Disks)配置慢。RAID讀寫速度受制於最慢的盤片,JBOD的磁盤操作都是獨立的。而且JBOD配置的HDFS某一磁盤故障可以直接忽略繼續工作,RAID有一個盤片壞了整個陣列都無法工作。

2.對於幾十個節點的小集羣,在一臺master機器上同時運行namenode和資源管理器通常可以接受,只要至少一份namenode的元數據被另存在HDFS中。但是集羣大了就應該分離這兩個角色在不同機子上。Namenode在內存中保存整個命名空間中所有文件元數據和塊元數據,內存需求很大,SecondaryNamenode在大多數時間空閒,但在創建檢查點時的內存需求與主namenode差不多

在分開的機器上運行master的主要理由是爲了高可用性。主master故障時備機將接替主機,在HDFS中輔助namenode的檢查點功能由備機執行,所以不需要同時運行備機和輔助namenode。

3.在網絡拓撲上,一般各機架裝配30-40個服務器,共享一個10GB的交換機,各機架的交換機又通過上行鏈路與一個核心交換機或路由器(10GB或更高)互聯,這種架構的特點是同一機架內部節點之間總帶寬高於不同機架上節點間的帶寬。讓Hadoop知道多機架集羣中機架和節點位置的關係很重要,可以在MapReduce任務分配到各節點時,傾向於執行機架內的數據傳輸,因爲機架內帶寬更大

Hadoop配置需要通過一個Java接口DNSToSwitchMapping指定節點地址和網絡位置間的映射關係。接口定義如下:

resolve()函數的輸入函數names描述IP地址列表,返回相應的網絡位置字符串列表。net.topology.node.switch.mapping.impl屬性實現了DNSToSwitchMapping接口。不過一般情況只需使用默認的ScriptBasedMapping實現即可,它運行用戶定義的腳本描述映射關係,腳本的存放路徑由屬性net.topology.script.file.name控制。腳本接受一系列輸入參數,描述帶映射的主機名稱或IP地址,再將相應的網絡位置以空格分開,輸出到實際輸出。

4.最好創建特定的Unix賬號以區分各Hadoop進程,及區分同一機器上其餘服務。HDFS、MapReduce和YARN服務通常作爲獨立的用戶運行,分別命名爲hdfs、mapred和yarn,同屬於一個hadoop組。可以將Hadoop安裝在/usr/local或者/opt目錄下,最好不要裝在/home目錄下。此外還需將Hadoop文件擁有者改爲hadoop用戶和組:

sudo chown –R /opt/hadoop-x.y.z

Hadoop控制腳本(不是守護進程)依賴SSH執行整個集羣的操作。爲了支持無縫式工作,需要允許來自集羣內機器的hdfs用戶和yarn用戶能夠無密碼登陸,需要以hdfs用戶身份設置一次,以yarn用戶身份一次設置以下命令:

ssh-keygen –t rsa –f ~/.ssh/id_rsa

私鑰放在由-f參數指定的文件中,存放公鑰的文件名稱與私鑰相同,但以“.pub”作爲後綴。接着,需確保公鑰存放在用戶打算連接的所有機器的~/.ssh/authorized_keys文件中,需要以hdfs用戶身份設置一次,以yarn用戶身份一次設置以下命令:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

放好公鑰後,用ssh命令測試能否連接到其他機器,若可以表明ssh-agent正在運行,再運行ssh-add命令存儲口令。

5.在使用HDFS前,需要使用hdfs namenode –format命令對namenode進行初始化。格式化進程將創建一個空的文件系統,該初始化過程不涉及datanode。Hadoop安裝目錄下的/sbin目錄放置了自帶的命令行腳本,可以在集羣內啓動和停止守護進程。namenode和資源管理器節點需要用到安裝目錄下的etc/hadoop/slaves文件,該文件包含了主機名或IP地址的列表,每行代表一臺機子,列舉了可以運行datanode和節點管理器(nodemanager)的機器。以hdfs用戶運行以下命令啓動HDFS守護進程:

start-dfs.sh

該腳本實質上做了以下事情:(1)在指定的機器上啓動namenode。(2)在etc/hadoop/slaves文件列舉的每臺機器上啓動一個datanode。(3)在指定的機器上啓動輔助namenode。

通過以下命令可以從fs.defaultFS屬性找到namenode的主機名:

hdfs getconf –namenodes

輔助namenode的屬性可從hdfs get conf -secondarynamenodes命令查到。

6.以yarn用戶在需要運行資源管理器的機器上運行以下命令啓動YARN:

start-yarn.sh

腳本具體完成以下事情:(1)在當前機器啓動一個資源管理器。(2)在etc/hadoop/slaves文件列舉的每臺機器上啓動一個節點管理器。

上述啓動各種守護進程的腳本實質上使用了/sbin/hadoop-daemon.sh。mapred用戶不需要使用SSH,MapReduce只有一個守護進程,即作業歷史服務器,通過mapred用戶用以下命令啓動:

mr-jobhistory-daemon.sh start historyserver

建立並運行Hadoop集羣后,需要給不同用戶設置用戶目錄以及訪問權限等,可以使用以下命令:

hadoop fs -mkdir /user/username
hadoop fs -chown username:username /user/username

可以使用以下命令給特定用戶目錄設置1TB的容量限制:

hdfs dfsadmin -setSpaceQuota 1t /user/username

7.Hadoop的重要配置文件都在安裝目錄的etc/hadoop目錄中。配置文件目錄可以放置在安裝目錄之外便於升級維護,只要啓動守護進程時使用--config參數或設置HADOOP_CONF_DIR環境變量。重要配置文件如下所示:

Hadoop沒有將所有配置信息放在一個全局位置中,而是集羣中每個節點各自保存一部分配置文件,由管理員同步對應配置文件。hadoop-env.sh可以設置環境變量,例如整個集羣的JAVA_HOME變量。MapReduce和YARN也有類似配置文件,名爲mapred-env.sh和yarn-env.sh,文件中的變量和組件相關,而且hadoop-env.sh中的全局設置值會被這兩個文件自己的設置覆蓋。

默認情況下,各守護進程被分配1000MB內存,由hadoop-env.sh文件的HADOOP_HEAPSIZE參數控制。也可以只爲某個守護進程修改堆大小,如在yarn-env.sh中設置YARN_RESOURCEMANAGER_HEAPSIZE覆蓋資源管理器的堆大小。對於namenode來說,1000MB內存的默認設置通常足夠管理數百萬個文件,但根據經驗,保守估計每一百萬個數據塊就需要分配1000MB內存空間。hadoop-env.sh文件的HADOOP_NAMENODE_OPTS屬性包含一個JVM選項以設定內存大小,可以傳遞例如-Xmx2000m參數表示爲namenode分配2000MB內存。由於輔助namenode的內存需求量與主namenode差不多,因此也同時需要對secondarynamenode做相同更改(HADOOP_SECONDARYNAMENODE_OPTS變量)。

默認系統日誌文件放在$HADOOP_HOME/logs目錄中,也可以改變hadoop-env.sh文件中的HADOOP_LOG_DIR變量來修改存放目錄。在實際商用中建議修改默認設置,使之獨立於Hadoop安裝目錄,即使Hadoop升級後安裝路徑發生變化,也不會影響日誌的位置,通常可以放在/var/log/hadoop目錄中。具體方法是在hadoop-env.sh中加入一行:

export HADOOP_LOG_DIR=/var/log/hadoop

8.運行在各機器上的Hadoop守護進程會產生兩類日誌文件。(1)第一類日誌文件以.log爲後綴,是通過log4j記錄的,大部分應用程序日誌都寫到這種日誌文件中,故障診斷首要步驟就是檢查這樣的文件。log4j配置採用日常滾動文件追加方式(daily rolling file appender)來循環管理日誌文件,系統不自動刪除過期日誌,而是等用戶定期刪除或存檔。(2)第二類日誌文件後綴爲.out,記錄標準輸出和標準錯誤日誌,因爲log4j已經記錄大部分日誌,這種文件只有少量紀錄或空記錄。重啓守護進程時,系統會創建一個新文件來記錄此類日誌。系統僅保留最新的5個日誌文件,舊的日誌會附加一個介於1和5的數字後綴,5爲最舊的文件,如下所示:

日誌文件的名稱包含運行守護進程的用戶名稱、守護進程名稱和本地主機名等信息。用戶名稱部分對應hadoop-env.sh中的HADOOP_IDENT_STRING變量。

9.SSH設置中,StrictHostKeyChecking設置爲no會自動將新主機鍵加到已知主機文件中,默認值是ask,提示用戶確認是否已驗證“鍵指紋”(key fingerprint),默認設置不適合大型集羣環境。hadoop-env.sh中的HADOOP_SSH_OPTS變量能向SSH傳遞更多參數。

10.對於真實工作集羣中非常關鍵的一些屬性在*-site.xml文件中。對於正在運行的守護進程,要知道實際配置可以在瀏覽器中訪問該進程的/conf頁面,例如http://<resourcemanager主機名>:8088/conf表示資源管理器當前運行配置。

運行HDFS需要有一臺機器指定爲namenode,core-site.xml中的fs.defaultFS設置文件系統或HDFS的URI,其主機名是主機名稱或IP地址,端口爲namenode監聽RPC的端口,默認端口爲8020。dfs.namenode.name.dir屬性指定一系列目錄來供namenode存儲備份永久性的文件系統元數據(編輯日誌和文件系統映像),這樣可以將namenode元數據寫到一兩個本地磁盤和一個遠程磁盤中,這樣即使本地磁盤故障,甚至整個namenode故障,都可以恢復元數據文件並重構新的namenode,而secondarynamenode只是定期保存namenode的檢查點,不一定來得及備份namenode最新數據。

dfs.datanode.data.dir屬性設定datanode存儲數據塊的目錄列表,循環地在各個目錄中寫入數據。因此爲了提高性能,最好分別爲各個本地磁盤指定一個存儲目錄,這樣數據塊跨磁盤分佈,針對不同數據塊的讀操作可以併發執行,提升讀取性能。爲了充分發揮性能,可以使用noatime參數掛載磁盤。該選項意味着執行讀操作時,讀取文件的最近訪問時間並不刷新,從而顯著提升性能。HDFS的關鍵配置屬性如下所示:

默認情況下,HDFS存儲目錄放在Hadoop臨時目錄下,該目錄通過hadoop.tmp.dir設置,默認值是/tmp/hadoop-username,如果設置別的值可以使得即使清除了系統的臨時目錄,數據也不會丟失。

11.運行YARN需要指定一臺機器作爲資源管理器,yarn.resourcemanager.hostname屬性設置用於運行resourcemanager的主機名或IP地址。執行MapReduce作業過程中產生的中間數據和工作文件被寫到臨時本地文件中,包括map任務的輸出數據。數據量可能很大,需要保證YARN本地臨時存儲空間(由yarn.nodemanager.local-dirs設置)足夠大。YARN沒有MapReduce1中的Tasktracker,它依賴shuffle將map任務輸出傳給reduce任務,因此需要將yarn-site.xml中的yarn.nodemanager.aux-services屬性設置爲mapreduce_shuffle來啓用MapReduce及shuffle功能。YARN的關鍵配置屬性如下所示:

12.在YARN中,允許爲一個任務請求任意在限制範圍內的規模的內存,因此一個節點上運行的任務數量取決於這些任務對內存的總需求量。每個Hadoop守護進程默認使用1000M內存,因此需要2000MB內存運行1個datanode和一個節點管理器。爲機器上運行的其他進程留出足夠內存後,通過yarn.nodemanager.resource.memory-mb屬性設置單位爲MB的內存總分配量,剩餘內存可用於節點管理器的container,默認爲8192MB,在大部分場景中太低。

爲單個作業設置內存選項有兩種方法:(1)控制YARN分配的容器大小。(2)控制容器中運行的Java進程堆大小。需注意的是,MapReduce的內存控制可以由客戶端在作業配置中設置,YARN設置是集羣層面的,客戶端不能修改。容器大小由屬性mapreduce.map/reduce.memory.mb決定,默認值都爲1024MB。Java進程的堆大小由mapred.child.java.opts設置,默認200MB,也可以單獨爲map和reduce任務設置Java選項,如下所示:

例如,mapred.child.java.opts設置爲-Xmx800m,mapreduce.map.memory.mb爲默認值,當map任務啓動時,節點管理器會爲該任務分配一個1024MB的容器,該任務運行期間nodemanager內存池會相應降低1024MB,並啓動配置爲最大堆爲800MB的任務JVM。然而,JVM進程的實際內存開銷會比該堆大小要大,JVM進程機器創建的子進程如Streaming使用的物理內存必須不超出分配的容器內存大小(該例子爲1024MB)。若某容器使用內存超出分配量,會被節點管理器終止並標記爲失敗。

容器的虛擬內存使用量如果超出預定係數和所分配物理內存的乘積,節點管理器也會終止進程,該係數由yarn.nodemanager.vmem-pmem-ratio設置,默認值2.1。YARN調度器默認情況下最小內存分配量爲1024MB(由yarn.scheduler.minimum-allocation-mb設置),默認最大內存分配量爲8192MB,屬性爲前者minimum處改爲maximum即可。

13.屬性yarn.nodemanager.resource.cpuvcores設置節點管理器分配給容器的CPU核數量。應該設置爲CPU總核數減去機器上運行的其他守護進程(datanode、nodemanager等)佔用的核數(每個進程佔用1個核)。設置屬性mapreduce.map/reduce.cpu.vcores屬性,可以使MapReduce作業能控制分配給map和reduce容器的核數量,兩者默認值均爲1。

Hadoop守護進程一般同時運行RPC和HTTP兩個服務器,RPC服務器支持守護進程間的通信,HTTP服務器提供與用戶交互的web頁面,需要爲各個服務器配置網絡地址和端口號。這些設置一方面決定了服務器將綁定的網絡接口,另一方面客戶端或集羣中其他機器使用它們連接服務器,例如節點管理器使用yarn.resourcemanager.resource.tracker.address屬性確定資源管理器的地址。

用戶經常希望服務器可以同時綁定多個網絡接口,將網絡地址設置爲0.0.0.0可達到該目的,但該地址無法被客戶端或集羣中其他機器解析。解決方法是將yarn.resourcemanager.hostname設爲主機名或IP地址,yarn.resourcemanager.bind-host設爲0.0.0.0,可確保資源管理器能與機器上所有網絡接口綁定,且同時能爲節點管理器和客戶端提供可解析的地址。

14.屬性dfs.hosts記錄允許作爲datanode加入集羣的機器列表,yarn.resourcenamanger.nodes.include-path記錄允許作爲節點管理器加入集羣的機器列表。dfs.host.exclude和yarn.resourcemanager.nodes.exclude-path所指定的文件包含待解除的機器列表。

Hadoop使用一個4KB的緩衝區輔助I/O操作。對於現代硬件來說容量過於保守,增大緩衝區容量會顯著提高性能,例如128KB更常用。可以在core-site.xml中的io.file.buffer.size屬性設置緩衝區大小,以字節爲單位。

默認情況下,HDFS塊大小爲128MB,但很多集羣將塊大小設置成兩倍或更大以降低namenode的內存壓力,並向mapper傳輸更多數據。可以通過hdfs-site.xml中的dfs.blocksize設置塊的大小,以字節爲單位。默認情況下datanode能使用存儲目錄上所有的閒置空間。如果想要把部分空間留給其他非HDFS應用程序,需要設置dfs.datanode.du.reserved屬性指定待保留的空間大小,也以字節爲單位。

Hadoop也支持回收站功能,被刪除文件可以不被真正刪除,僅轉移到回收站的一個特定文件夾中。回收站文件被永久刪除之前仍會保留一段時間,該時間間隔由core-site.xml中的fs.trash.interval屬性以分鐘爲單位設置,默認情況該值爲0,即不啓用回收站。這種回收站功能只有由系統shell直接刪除的文件纔會被放到回收站,用程序刪除的一般會直接刪除,除非構造一個Trash類的實例,調用moveToTrash()方法把指定路徑文件移到回收站中。如果成功返回true,否則如果回收站功能未啓用,或該文件已在回收站中,會返回false。

當回收站功能啓用時,每個用戶都有獨立回收站目錄,即/home目錄下的.Trash目錄,恢復文件只需要在.Trash的子目錄中找到文件並移出該文件夾即可。只有HDFS會自動刪除回收站中的文件,其他文件系統沒有該功能,需要利用以下命令手動定期刪除已在回收站中超過最小時限的所有文件:

hadoop fs -expunge

Trash類的expunge()方法也有相同效果。

15.在默認情況下調度器會一直等待,直到該作業的5%的map任務已經結束纔會調用reduce任務。對大型作業來說會降低集羣利用率,因爲在等待map任務執行完畢的過程中,佔用了reduce容器。可以將mapreduce.job.reduce.slowstart.completedmaps的值設置的更大例如0.80(80%),能夠提升吞吐率

從HDFS讀取文件時,客戶端聯繫datanode然後數據通過TCP連接發送給客戶端,如果正在讀取的數據塊就在客戶端節點上,可以繞過網絡直接讀取本地磁盤上的數據更有效率,即短迴路本地讀”(short-circuit local read),該方式能讓HBase等應用執行效率更高。將dfs.client.read.shortcircuit設置爲true可啓用該功能。該讀操作基於Unix套接字實現,在客戶端和datanode之間的通信中使用一個本地路徑,該本地路徑由dfs.domain.socket.path設置,且必須是一條僅由datanode或root用戶能創建的路徑,例如/var/run/hadoop-hdfs/dn_socket。

16.在安全性方面,Hadoop使用Kerberos(一個成熟開源網絡認證協議)實現用戶認證,該協議的職責是鑑定登錄賬號是否就是真的用戶,而不是僞造身份的攻擊者,而Hadoop本身決定該用戶擁有哪些權限。使用Kerberos時一個客戶端要經過三個步驟才能獲得服務,每個步驟客戶端需要和服務器交換報文,如下所示:

(1)認證。客戶端向認證服務器發送一條報文,並獲取一個含時間戳的憑據授予憑據(Ticket-Granting Ticket,TGT)。

(2)授權。客戶端使用TGT向憑據授予服務器(Ticket-Granting Server,TGS)請求一個服務憑據。

(3)服務請求。客戶端向對應服務器出示服務憑據,以證實自己的合法性,該服務器(namenode或resourcemanager)提供客戶端所需服務。

這樣認證服務器和憑據授予服務器構成了密鑰分配中心(Key Distribution Center,KDC)。客戶端系統會代替用戶執行這些步驟,但認證步驟需要用戶調用kinit命令執行,該過程會提示輸入密碼,在TGT有效期內(默認10小時,可調整到一週)不需要輸入第二次。更好的做法是採用自動認證,在登錄操作系統的時候自動執行認證操作,從而只需單次登錄Hadoop。如果需要運行一個無人值守的MapReduce作業等用戶不希望提示輸入密碼的場合,可以使用ktutil命令創建一個Kerberos的keytab文件,該文件保存了用戶密碼並且可以通過-t選項應用於kinit命令。

舉個例子,首先將core-site.xml文件中hadoop.security.authentication屬性設置爲kerberos,啓動Kerberos認證(需提前安裝配置好並運行一個KDC),該屬性默認值爲simple,即利用操作系統用戶名來決定登陸者身份。其次,同一文件中的hadoop.security.authorization屬性設置爲true,以啓用服務級別的授權,可配置$HADOOP_HOME/etc/hadoop目錄下的hadoop-policy.xml文件中的訪問控制列表以決定哪些用戶和組能夠訪問哪些Hadoop服務,默認情況下各個服務的訪問控制列表都爲*,即所有用戶能訪問所有服務,包括針對MapReduce作業提交的服務,針對namenode通信的服務等。具體在這種安全認證下複製本地文件到HDFS的命令行例子如下:

17.在kinit命令後,後續認證訪問由委託令牌完成,避免在一個高負載集羣中,HDFS的客戶端與namenode和datanode頻繁交互給KDC帶來巨大壓力。委託令牌由服務器創建,在HDFS中爲namenode創建,可視爲客戶端和服務器間共享的一個密文。客戶端首次通過RPC訪問namenode時,客戶端沒有委託令牌,因此需要通過Kerberos認證,之後客戶端從namenode獲得一個委託令牌,在後續RPC調用中,客戶端只需出示委託令牌,namenode就能驗證令牌真僞(因爲是namenode使用密鑰創建的)。

在不安全的Hadoop系統中,客戶端只需要知道某個HDFS塊的塊ID即可訪問該數據塊,在安全機制下客戶端需要塊訪問令牌(block access token)才能訪問特定的HDFS塊。當客戶端向namenode發出元數據請求時,namenode創建相應的塊訪問令牌返回客戶端,客戶端使用這個令牌向datanode認證自己的訪問權限(因爲namenode和datanode之間有心跳同步機制,也會同步令牌密鑰)。要訪問不同的數據塊需要不同的塊訪問令牌。可以將dfs.block.access.token.enable設置爲true開啓塊訪問令牌功能。作業結束時,委託令牌失效。

18.在集羣建立好並開始正式工作前,最好運行一下基準評測程序,並且不同時運行其他任務以獲得最佳評測效果。如果不指定參數,大多數基準測試程序都會顯示具體用法,如下所示:

Hadoop自帶一個名爲TeraSort的MapReduce程序,該程序對輸入進行全排序。全部輸入數據集通過shuffle傳輸,因此對於同時評測HDFS和MapReduce很有用。測評分爲三步:生成隨機數據、執行排序和驗證結果:

(1)首先,使用teragen生成隨機數據,它運行一個僅有map任務的作業,可生成指定行數的二進制數據,每一行100字節長,這樣使用1000個map任務可生成10TB數據,命令如下(10t爲10trillion的意思):

hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar \
teragen -Dmapreduce.job.maps=1000 10t random-data

(2)接下來運行TeraSort:

hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar \
terasort random-data sorted-data

排序的總執行時間是有用的度量值,可以通過瀏覽器內訪問http://<resource-manager-host>:8088/查看作業進度。

(3)最後,驗證在sorted-data文件中的數據是否已經排好序:

hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar \
teravalidate sorted-data report

該命令運行一個小的MapReduce作業,對排序後數據進行檢查,任何錯誤可從輸出文件report/part-r-00000中找到。常用的基準測評程序如下所示:

如果所測集羣是該用戶第一個集羣,且還沒有任何作業,Gridmix或SWIM都是推薦的評測方案。

19.運行中的namenode有如下所示的目錄結構,各個目錄存儲着鏡像內容,該機制使系統具備一定復原能力,尤其是其中某個目錄爲NFS時:

VERSION文件是一個Java屬性文件,包含正在運行的HDFS版本信息,一般包括如下內容:

layoutVersion是一個負整數,描述HDFS佈局的版本,該版本號與Hadoop版本無關,只要佈局變更,版本號遞減(例如變爲-58),此時HDFS也需要更新,否則磁盤依然使用舊版本佈局,新版本namenode或datanode會無法正常工作。namespaceID是文件系統命名空間的唯一標識符,是在namenode首次格式化時創建的。clusterID是整個HDFS集羣的唯一標識符,用於區分聯合HDFS內多個HDFS集羣。blockpoolID是數據塊池的唯一標識符,池中包含一個namenode管理的命名空間中的所有文件。

cTime屬性標記了namenode存儲系統的創建時間,剛格式化的存儲系統值爲0,文件系統數據更新後會有新的時間戳。storageType屬性說明該存儲目錄包含的是namenode的數據結構。in_use.lock文件是一個鎖文件,namenode使用該文件爲存儲目錄加鎖,可避免其他namenode實例同時使用甚至破壞同一個存儲目錄。

20.文件系統客戶端執行寫操作時(如創建和移動文件),這些事務先記錄到編輯日誌中,namenode在內存中維護文件系統的元數據;當編輯日誌被修改時,相關元數據信息也同步更新。編輯日誌概念上雖然像單個實體,實質上是磁盤上的多個文件,每個文件稱爲一個“段”(segment),名稱由前綴edits及後綴組成,後綴是該文件所包含的事務ID。任一時刻只有一個文件處於打開可寫狀態,例如上面的edits_inprogress_XXXX。在每個事務完成之後並在向客戶端發送成功碼之前,文件都需要更新和同步。當namenode向多個目錄寫數據時,只有在所有操作更新並同步到每個副本之後纔可返回成功碼。

每個fsimage文件都是文件系統元數據的一個完整的永久性檢查點,前綴中的序號表示映像文件中的最後一個事務。如果namenode發生故障,最近的fsimage文件將被載入到內存以重構元數據的最近狀態,再從相關點開始向前執行編輯日誌中記錄的每個事務。事實上namenode在啓動階段也是這樣做的。

如上所述,編輯日誌會無限增長,由於需要恢復非常長的編輯日誌中的各項事務,故障namenode的重啓會比較慢,解決方案是運行輔助namenode,爲主namenode內存中的文件系統元數據創建檢查點。創建檢查點步驟如下所示:

(1)輔助namenode請求主namenode停止使用正在進行中的edits文件,這樣新的編輯操作記錄到一個新文件中。主namenode還會更新所有存儲目錄中的seen_txid文件。

(2)輔助namenode從主namenode獲取最近的fsimage和edits文件,採用HTTP GET方式。

(3)輔助namenode將fsimage文件載入內存,逐一執行edits文件中的事務,創建新的合併後的fsimage文件。

(4)輔助namenode將新的fsimage文件發送回主namenode(使用HTTP PUT方式),主namenode將其保存爲臨時的.ckpt文件。

(5)主namenode重新命名臨時的fsimage文件,便於日後使用。

最終,主namenode擁有最新的fsimage文件和一個更小的edits-inprogress文件。當namenode處在安全模式時,管理員也可調用hdfs dfsadmin -saveNamespace命令來創建檢查點。因此該過程解釋了輔助namenode與主namenode有相近內存需求的原因,即輔助namenode也把fsimage文件存入自己的內存。因此大型集羣中Secondarynamenode需要運行在另一臺機子上的原因。

創建檢查點的觸發條件受兩個參數控制:(1)輔助namenode默認每隔一小時(由dfs.namenode.checkpoint.period設置,以秒爲單位)創建檢查點。(2)如果從上一個檢查點開始編輯日誌的大小已經達到默認100萬個事務(由dfs.namenode.checkpoint.txns設置),即使不到創建間隔也會創建檢查點,檢查數量的頻率默認爲每分鐘一次(由dfs.namenode.checkpoint.check.period設置,以秒爲單位)。

21.輔助namenode的檢查點目錄(dfs.namenode.checkpoint.dir)的佈局和主namenode檢查點目錄的佈局相同,如下所示:

從輔助namenode恢復數據有兩種方法:(1)將該存儲目錄複製到新的namenode中。(2)使用-importCheckpoint參數啓動namenode守護進程,從而將輔助namenode作爲新的主namenode。藉助該參數,僅當dfs.namenode.name.dir屬性定義的目錄中沒有元數據時,輔助namenode會從dfs.namenode.checkpoint.dir屬性定義的目錄中載入最新的檢查點namenode元數據,因此不會覆蓋現有元數據。

22.datanode與namenode不同,它的存儲目錄是初始階段自動創建的,不需要用格式化命令。datanode的目錄結構如下所示:

HDFS數據塊存儲在以blk_爲前綴名的文件中,文件名包含了該文件存儲的塊的原始字節數。每個塊有一個相關聯的帶有.meta後綴的元數據文件。元數據文件包括頭部(含版本和類型信息)和該塊各區段的一系列校驗和。每個塊屬於一個數據塊池(blockpool),每個數據塊池都有自己的存儲目錄,目錄名與namenode的VERSION文件中的blockpoolID相同。

當目錄中數據塊數量增加到默認64個數據塊(由dfs.datanode.numblocks設置)時,就創建一個子目錄存放新的數據塊及其元數據信息。這樣即使HDFS中塊數量很多,目錄樹的層數也不多,便於管理。如果dfs.datanode.data.dir屬性指定了不同磁盤上的多個目錄,那麼數據塊會以輪轉方式寫到各個目錄中,同一個datanode上每個磁盤上的塊不會重複,但是不同datanode之間的塊可能重複。

23.namenode啓動時,首先將映像文件fsimage載入內存,並執行編輯日誌edits中的各項編輯操作,一旦在內存中成功建立文件系統元數據的映像,則創建一個新的fsimage文件和一個空的新編輯日誌,這個過程中namenode的文件系統對於客戶端來說是隻讀的(例如顯示文件列表)還不能進行文件修改操作(寫、刪除或重命名),稱爲安全模式

一開始系統中數據塊的位置不由namenode維護,而是以塊列表的形式存儲在datanode中。在系統操作期間,namenode會在內存中保留所有塊位置的映射信息。在安全模式下,各datanode會向namenode發送最新的塊列表信息。如果滿足最小副本條件(minimal replication condition),namenode會在30秒鐘後退出安全模式,該條件即整個HDFS中有99.9%的數據塊滿足最小副本數量(默認值爲1,由dfs.namenode.replication.min設置)。如果是啓動一個新的剛格式化的HDFS集羣,系統中沒有任何數據塊,所以namenode不會進入安全模式。

要查看namenode是否處於安全模式,可以使用如下命令,或從HDFS的網頁頁面查看:

hdfs dfsadmin -safemode get

有時用戶希望先退出安全模式啓動某個其他命令,可以用以下命令:

hdfs dfsadmin -safemode wait
#command to read or write a file

在維護和升級集羣時,管理員可以隨時將namenode進入或離開安全模式,因爲需要確保數據在指定時間段內只讀,使用以下命令進入安全模式:

hdfs dfsadmin -safemode enter

運行以下命令可以使namenode離開安全模式:

hdfs dfsadmin -safemode leave

24.HDFS日誌能夠記錄所有文件系統訪問請求,對日誌進行審計是log4j在INFO級別實現的。默認情況沒有啓用該特性,可以在$HADOOP_HOME/etc/hadoop/hadoop-env.sh文件中增加下面這行狀態變量啓用日誌審計:

export HDFS_AUDIT_LOGGER=”INFO,RFAAUDIT”

每個HDFS事件均在審計日誌hdfs-audit.log中生成一行日誌記錄。hdfs dfsadmin命令用途較廣,可以查找HDFS狀態信息,又可以在HDFS上執行管理操作,該命令一般需要超級用戶權限,部分命令參數如下:

25.hdfs fsck命令檢查HDFS中文件健康情況,例如所有datanode中缺失的塊以及過少或過多的塊,如下所示:

其中Over-replicated blocks表示副本數超過最小副本數量的塊,HDFS會自動刪除多餘副本;Under_replicated blocks表示副本數少於最小副本數量的塊,HDFS會自動創建新副本;Mis-replicated blocks表示違反副本放置策略的塊,例如默認最少副本數爲3的多機架集羣中,若一個數據塊的三個副本都放在同一個機架裏,可認定該塊的副本放置錯誤,應該兩個在本機架,一個在另一個機架;Corrupt blocks表示所有副本都已損壞的塊;Missing replicas表示集羣中沒有任何副本的塊。要注意的是,fsck命令只從namenode獲取數據塊的元數據信息,不與任何datanode進行交互

損壞的塊和缺失的塊最需要注意,因爲這意味着數據已經丟失了。此時有兩種選擇:(1)使用hdfs fsck -move命令將受影響的文件移到HDFS的/lost+found目錄,這些文件會分裂成連續的塊鏈表幫助挽回損失。(2)使用-delete參數刪除受影響的文件。

hdfs fsck命令還可以幫助用戶找到屬於特定文件的數據塊,例如:

該輸出表示文件/user/tom/part-00007包含一個數據塊,該塊三個副本存儲在最後三個datanode上。-files參數顯示第一行信息,包括文件名稱、大小、塊數量和健康狀況(是否有缺失的塊)。-blocks參數描述文件中各個塊的信息,每個塊一行。-racks參數顯示每個塊的機架位置和datanode的地址。

26.各datanode運行一個塊掃描器,默認每504小時(三週,由dfs.datanode.scan.period.hours設置)通過掃描器維護的塊列表依次掃描檢測本節點上的所有塊,從而在客戶端讀到壞塊之前及時檢測並報告給namenode修復塊。掃描器使用了節流機制,塊掃描器工作時僅佔用一小部分磁盤帶寬。用戶通過網頁http://<datanode>:50075/blockScannerReport獲取datanode的塊檢測報告,報告示例如下所示:

通過在地址欄裏指定listblocks參數,即http://<datanode>:50075/blockScannerReport?Listblocks,會在報告中列出該datanode上所有的塊及其最新驗證狀態,如下所示:

第一列是塊ID,後面是鍵值對,塊的狀態(status)要麼是failed,要麼ok,由最近一次塊掃描是否檢測到校驗和決定,掃描類型(type)可以是local、remote或none。如果掃描操作由後臺線程執行則爲local;如果掃描操作由客戶端或其他datanode執行則爲remote;如果針對該塊的掃描尚未執行則爲none。最後一項信息是掃描時間,從1970/01/01午夜開始的毫秒數。

27.隨着時間推移,各datanode上的塊分佈會越來越不均衡,不均衡的集羣會降低MapReduce的數據本地性,導致部分datanode相對更加繁忙,需要避免這種情況。均衡器(balancer)程序是一個Hadoop守護進程,將塊從忙碌的datanode移到相對空閒的datanode,重新分配塊,同時堅持副本放置原則,將副本分散到不同機架,直到每個datanode的使用率(已用空間/總空間)和集羣使用率非常接近,差距不超過給定閾值。調用下列命令啓動均衡器:

start-balancer.sh

-threshold參數指定閾值(百分比格式)。若省略,默認閾值是100%,任何時刻,集羣中都只運行一個均衡器。均衡器使集羣變得均衡之後,就不能再移動塊,並且也要保持與namenode的連接。均衡器在標準日誌目錄中創建一個日誌文件,記錄它執行的每輪重新分配過程,每輪次輸出一行,如下所示:

爲降低集羣負荷,均衡器在後臺運行,在不同節點之間複製數據的帶寬是有限的,默認值很小爲1MB/s,可通過hdfs-site.xml中的dfs.datanode.balance.bandwidthPerSec屬性設置,單位爲字節。

28.所有Hadoop守護進程都會產生日誌文件,可以通過守護進程的網頁(守護進程網頁的/logLevel目錄下)改變任何log4j日誌的日誌級別,例如啓用資源管理器相關所有類的日誌調試特性,可以訪問http://resource-manager-host:8088/logLevel,並將日誌名org.apache.hadoop.yarn.server.resourcemanager設置爲DEBUG級別,也可以用以下命令:

hadoop daemonlog -setlevel resource-manager-host:8088 \
org.apache.hadoop.yarn.server.resourcemanager DEBUG

上面兩個方式修改的日誌級別會在守護進程被重啓時重置。如果要永久變更日誌級別,需要在$HADOOP_HOME/etc/hadoop/log4j.properties文件中添加如下賦值代碼:

log4j.logger.org.apache.hadoop.yarn.server.resourcemanager=DEBUG

Hadoop守護進程還提供一個網頁(對應節點頁面的/stacks子地址)對守護進程的JVM中運行的線程執行線程轉儲(thread dump,指JVM某一個時刻運行的所有線程的快照,每個線程都有自己的調用堆棧,在一個給定時刻體現爲一個獨立功能。線程轉儲會提供JVM中所有線程的堆棧信息)。例如,可通過http://resource-manager-host:8088/stacks獲得資源管理器的線程轉儲,如下所示:

29.Hadoop守護進程收集事件和度量相關的信息,這些信息稱爲“度量”(metric)。例如各datanode會收集以下度量:寫入字節數、塊的副本數和客戶端發起的讀操作請求數等。其中dfs、mapred、yarn和rpc爲四個方面的度量場景,例如datanode會分別爲dfs和rpc場景收集度量。

度量與計數器的不同點有:(1)度量由守護進程收集,而計數器先針對MapReduce任務進行採集,再針對整個作業進行彙總。(2)用戶羣不同,度量爲管理員服務,計數器主要爲MapReduce用戶服務。(3)數據採集和聚集過程不同。MapReduce系統確保計數器值由任務JVM產生,再傳回application master,最終傳回運行作業的客戶端。整個過程中任務進程和application master都會執行彙總操作;而度量的收集機制獨立於接收更新的組件,有多種輸出度量的方式包括本地文件和JMX等。守護進程收集度量,並在輸出之前執行彙總操作。

Hadoop度量可以使用JMX工具例如JDK自帶的JConsole查看。如果是遠程訪問需要將JMX系統屬性com.sun.management.jmxremote.port及其他一些用於安全的屬性設置爲允許訪問。例如在namenode實現該功能,需要在$HADOOP_HOME/etc/hadoop/hadoop-env.sh文件中設置以下語句:

HADOOP_NAMENODE_OPTS=”-Dcom.sun.management.jmxremote.port=8004”

也可以通過特定守護進程的/jmx網頁查看該守護進程的JMX度量(JSON格式),例如在網頁http://namenode-host:50070/jmx查看namenode的度量,如下所示:

30.如果namenode永久性元數據丟失或破壞,則整個文件系統無法使用,因此備份元數據非常關鍵。可以在系統中分別保存若干份不同時間的備份,最直接的元數據備份方法是使用hdfs dfsadmin命令下載namenode最新的fsimage文件的副本:

hdfs dfsadmin -fetchImage fsimage.backup

備份原則是無法重新生成的數據的優先級最高,這些數據對業務非常關鍵,而可再生數據和一次性數據價值有限,優先級最低無需備份。distcp是一個理想的備份工具,其並行的文件複製功能可以將備份文件存儲到其他HDFS集羣或例如亞馬遜S3等其他文件系統中。HDFS還允許用戶對文件系統進行快照,快照是對文件系統在給定時刻的一個只讀副本,由於並不真正複製數據,因此快照非常高效,它們簡單地記下每個文件的元數據和塊列表,對於重構快照時刻的文件系統已經足夠。

日常的集羣維護有以下事務:(1)元數據備份。(2)HDFS數據備份。(3)定期在整個文件系統上運行fsck命令,主動查找丟失或損失的塊。(4)定期運行均衡器使各datanode比較均衡。

31.集羣需要經常添加節點或移除節點,例如爲了擴大容量,需要委任節點,如果需要縮小集羣規模或者某些節點表現反常,故障率過高或性能過於低下等,需要解除節點。通常節點同時運行datanode和節點管理器,所以兩者一般同時被委任或解除。允許連接到namenode的datanode列表放在namenode的一個文件中,文件名稱由dfs.hosts屬性指定,該文件每行對應一個datanode的網絡地址。

同樣,連接到資源管理器的各節點管理器也在同一個文件中指定(文件名由yarn.resourcemanager.nodes.include-path指定)。通常集羣中的節點同時運行datanode和節點管理器的守護進程,dfs.host和yarn.resourcemanager.nodes.include-path會同時指向一個文件,即$HADOOP_HOME/etc/hadoop/include文件。向集羣添加新節點的步驟如下

(1)將新節點的網絡地址添加到include文件中。

(2)運行以下指令,將新增的datanode更新至namenode信息:

hdfs dfsadmin -refreshNodes

(3)運行以下指令,將新增的節點管理器更新至資源管理器:

yarn rmadmin -refreshNodes

(4)將新節點的列表寫入更新slaves文件(含有datanode與nodemanager地址列表),這樣Hadoop控制腳本會將新節點包括在未來操作中。

(5)啓動新的datanode和nodemanager。

(6)檢查新的datanode和節點管理器是否都出現在網頁界面中。

HDFS不會自動將塊從舊datanode移到新的datanode以平衡集羣,需要手動運行均衡器

32.解除舊節點時,需要解除的節點列表需要放到exclude文件中,對於datanode該文件由dfs.hosts.exclude屬性設置,對於YARN來說由yarn.resourcemanager.nodes.exclude-path設置。通常這兩個屬性指向同一個文件。判斷一個nodemanager是否能連接到資源管理器很簡單,當節點管理器地址出現在include文件且未出現在exclude文件中時纔可。如果未指定include文件或文件內爲空,則意味着所有節點都包含在include文件中;而對於HDFS不同,如果一個datanode同時出現在include和exclude文件中,意味着該節點可連接但馬上會被解除,如果一個datanode沒有出現在include和exclude文件中,則節點無法連接。移除節點的步驟如下

(1)將待解除節點的網絡地址添加到exclude文件中,不更新include文件。

(2)執行以下命令,刷新namenode設置:

hdfs dfsadmin -refreshNodes

(3)執行以下命令,刷新資源管理器設置:

yarn rmadmin -refreshNodes

(4)轉到網頁界面,查看待解除datanode的管理狀態是否已變爲“正在解除”(Decommission In Progress),此時這些datanode會把它們的塊複製到其他datanode中。

(5)當所有待解除datanode的狀態變爲“解除完畢”(Decommissioned)時,表明所有塊已複製完畢,關閉已經解除的節點。

(6)從include文件中移除這些節點地址,並運行以下命令:

hdfs dfsadmin -refreshNodes
yarn rmadmin -refreshNodes

(7)從slaves文件中移除節點。

33.在升級集羣系統時,需要考慮API兼容性、數據兼容性和連接兼容性。其中連接兼容性的規則是,客戶端與服務器必須有相同的主版本號,但次版本號或單點發行版本號可以不同,例如客戶端2.0.2版可和服務器2.1.0版工作,但不可和服務器3.0.0版工作。如果文件系統佈局沒有改變,升級集羣非常容易:關閉舊守護進程,在集羣上安裝新版本Hadoop,升級配置文件,啓動新守護進程,令客戶端使用新的庫,該過程可逆可還原爲舊版本。

成功升級版本後,還需要執行兩個清理步驟:(1)從集羣中移除舊的安裝和配置文件。(2)對代碼和配置文件中針對“被棄用”(deprecation)警告信息進行修復。Cloudera Manager和Apache Ambari等集羣管理軟件升級過程更容易,它們使用滾動升級,節點以批量方式升級,這樣客戶端不會感受到服務中斷。

不過如果新舊HDFS的文件系統佈局不同,則按照上述升級方法會使namenode無法工作,會在日誌文件中產生如下信息:

升級HDFS會保留前一版本的元數據和數據副本,不過並不需要兩倍存儲開銷,因爲datanode使用硬連接保存指向同一個數據塊的兩個應用(當前版本和前一版本),這樣可以方便回滾到前一個版本,但只能回滾到前一個版本不能前幾個版本。下次升級HDFS數據和元數據前,需要刪除這次升級保留的前一版本,該過程稱爲“定妥升級”(finalizing the upgrade)。一旦執行該操作,就無法回滾到該前一版本。

僅當文件系統健康時才能升級,因此有必要在升級前調用hdfs fsck命令全面檢查文件系統狀態。而且最好保留該檢查輸出報告,升級後再次運行該命令檢查一遍,對比兩份檢查報告的內容。在升級前最好清空臨時文件,包括HDFS的MapReduce系統目錄和本地臨時文件等。因此,如果升級集羣會導致文件系統佈局變化,需要採用以下步驟升級

(1)在執行升級任務之前,確保前一升級已經定妥。

(2)關閉YARN和MapReduce守護進程。

(3)關閉HDFS,並備份namenode目錄。

(4)在集羣和客戶端安裝新版本的Hadoop。

(5)使用-upgrade選項啓動HDFS。

(6)等待,直到升級完成。

(7)檢驗HDFS是否運行正常,例如使用fsck,檢驗時使HDFS進入安全模式。

(8)啓動YARN和MapReduce守護進程。

(9)回滾或定妥升級任務(可選)。

運行升級任務時,最好移除PATH環境變量下的Hadoop腳本,這樣用戶不會混淆不同版本的腳本。通常可以爲新的安裝目錄定義兩個環境變量,例如OLD_HADOOP_HOME和NEW_HADOOP_HOME。在步驟(5)中,爲了執行升級,可運行如下命令:

$NEW_HADOOP_HOME/bin/start-dfs.sh -upgrade

該命令的結果是讓namenode升級元數據,將前一版本放在dfs.namenode.name.dir下的名爲previous的新目錄中。同樣datanode升級存儲目錄,保留原先副本,將其存放在previous目錄中。步驟(6)等待升級過程時,可以用以下命令查看升級進度,升級事件也會出現在守護進程的日誌文件中:

$NEW_HADOOP_HOME/bin/hdfs dfsadmin -upgradeProgress status

步驟(9)中如果新版本無法正常工作,可以回滾到前一版本。首先關閉新的守護進程:

$NEW_HADOOP_HOME/bin/stop-dfs.sh

然後使用-rollback選項啓動舊版本HDFS:

$OLD_HADOOP_HOME/bin/start-dfs.sh -rollback

該命令會讓namenode和datanode使用升級前的副本替換當前的存儲目錄,文件系統返回之前的狀態。如果滿足最新版本的HDFS,要定妥升級移除升級前的存儲目錄,需要執行以下命令:

$NEW_HADOOP_HOME/bin/hdfs dfsadmin -finalizeUpgrade
$NEW_HADOOP_HOME/bin/hdfs dfsadmin -upgradeProgress status

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章