1. 程式人生 > >Hadoop叢集datanode磁碟不均衡的解決方案【轉】

Hadoop叢集datanode磁碟不均衡的解決方案【轉】

一、引言:

Hadoop的HDFS叢集非常容易出現機器與機器之間磁碟利用率不平衡的情況,比如叢集中新增新的資料節點,節點與節點之間磁碟大小不一樣等等。當hdfs出現不平衡狀況的時候,將引發很多問題,比如MR程式無法很好地利用本地計算的優勢,機器之間無法達到更好的網路頻寬使用率,機器磁碟無法利用等等。 二、問題: 因業務需要搭建一個新hadoop叢集,並將老的hadoop叢集中的資料遷移至新的hadoop叢集,而且datanode節點不能全部上線,其中還可能會出現節點上線或下線的情況,這個時候就很容易出現機器與機器之間磁碟的均衡的情況,具體如下: 上圖中可以看出max是94.18%,而min是0.37%,其中有600多臺是達到94%的,這個時候在跑mapred的時候往往會報錯誤:
登陸到該機器上檢視伺服器的磁碟,磁碟都快已經達到100%,如下: 因為我們在hdfs-site.xml中設定了dfs.datanode.du.reserved的值,所以磁碟會有一定預留空間:
<property>
    <name>dfs.datanode.du.reserved</name>
    <value>107374182400</value>
</property>

上面這個引數的意思:

  Reserved space in bytes per volume. Always leave this much space free for non dfs use.

再檢視datanode日誌,希望能找到可靠的線索:

這種錯誤無法通過namenode來避免,因為它不會再failed的時候去嘗試往別的節點寫數, 最初的辦法是將該節點的datanode關閉掉,就能順利地跑完這個mapreduce。

再者檢視namenode的頁面,看到有好多datanode的節點的Remaining快要趨於0B了,這個時候就很容易出現上面的報錯。

為了防止上面的報錯再次出現以及避免hdfs資料不均衡,對hadoop叢集做balance已經不可避免了! 二、解決方案 1、balancer 大家首先會想到hadoop自帶的balancer,那就先介紹一下balancer! Balancer.java中是這麼描述balancer的:

The balancer is a tool that balances disk space usage on an HDFS cluster when some datanodes become full or when new empty nodes join the cluster.
The tool is deployed as an application program that can be run by the cluster administrator on a live HDFS cluster while applications adding and deleting files.

下面的圖片是官網中balancer命令得詳解:

考慮到balancer是最近需要經常做的操作,所以我們自己開發了一個檢視balancer情況的頁面,結果如下: 上圖可以看到每個叢集下balancer執行情況。 balance一天能成功移動的資料量大約在10-20T,這個資料量很難滿足超大叢集。 目前我們呼叫balance會使用如下命令:
start-balancer.sh -threshold 20 -policy blockpool -include -f /tmp/ip.txt
上面的命令通過手工篩選出磁碟高的和磁碟低的放在ip.txt檔案中,這樣balance就只通過這檔案裡的了,另外還需要設定適當的threshold值,因為是多namespace的,所以需要選擇blockpool模式。 另外頻寬也是限制balance的一個因素,在hdfs-site.xml中是有設定的:
<property>
    <name>dfs.datanode.balance.bandwidthPerSec</name> 
    <value>10485760</value> 
</property>

但是這個需要重啟,hadoop提供了一個動態調整的命令:

hdfs dfsadmin -fs hdfs://ns1:8020 -setBalancerBandwidth 104857600
hdfs dfsadmin -fs hdfs://ns2:8020 -setBalancerBandwidth 104857600
hdfs dfsadmin -fs hdfs://ns3:8020 -setBalancerBandwidth 104857600
hdfs dfsadmin -fs hdfs://ns4:8020 -setBalancerBandwidth 104857600
hdfs dfsadmin -fs hdfs://ns5:8020 -setBalancerBandwidth 104857600
  2、上下節點: 其實將高磁碟的節點強制Decommission是最快最有效的方案。 下節點的時候可能會出現有ns不能正常下掉的情況,其實這個時候節點的資料大部分已經移出去了,可能有一些塊卡在那邊沒有移出去。 這個時候只能一個一個節點將已經Decommissioned節點stop掉datanode程序,如果在namenode的頁面上看到有丟失塊的話,就需要將這個塊先get到本地,在put上去。例如:
hdfs dfs -get hdfs://ns1/test/dt=2016-07-24/000816_0.lzo
 
hdfs dfs -put -f 000816_0.lzo hdfs://ns1/test/dt=2016-07-24/000816_0.lzo
 
hdfs dfs -chown dd_edw:dd_edw hdfs://ns1/test/dt=2016-07-24/000816_0.lzo  

前提條件需要將這個節點的datanode重新啟動。

3、升降資料副本: 升降副本是一個迫不得已的辦法,這樣如果datanode有掛掉節點,就會增加丟失塊的機率。 具體降副本的命令如下:
hdfs dfs -setrep -R -w 2 hdfs://ns1/tmp/test.db

升副本的命令如下:

hdfs dfs -setrep -R -w 3 hdfs://ns1/tmp/test.db

上面的命令是將ns1下的/tmp/test.db副本數降至2個,然後又將它升至3哥副本。具體的hdfs dfs -setrep命令如下圖:

這樣動態的升降副本可以解決。

另外在升降副本的遇到一個BUG:

推測可能是namenode的replications模組有夯住情況,所以出現該情況執行kill掉進行,跳過該塊再跑!

總結:之所以選擇使用升降副本是因為它不受頻寬的控制,另外在升降副本的時候hadoop是需要重新寫數的,這個時候它會優先往磁碟低寫資料,這樣就能將磁碟高的資料遷移至磁碟低的。

4、distcp

DistCp (distributed copy) is a tool used for large inter/intra-cluster copying. It uses MapReduce to effect its distribution, error handling and recovery, and reporting. It expands a list of files and directories into input to map tasks, each of which will copy a partition of the files specified in the source list. Its MapReduce pedigree has endowed it with some quirks in both its semantics and execution. The purpose of this document is to offer guidance for common tasks and to elucidate its model.

在這裡舉一個例子:

通過distcp將/tmp/output12上的資料呼叫mapreduce遷移至/tmp/zhulh目錄下,原先/tmp/output12上的資料還是有存在的,但是它的塊就發生了變化。

這個時候有人可能會說怎麼不使用cp命令呢?

兩者的區別如下:

CP的模式是不走mapreduce的;DISTCP的模式是走mapreduce的,所以它優先寫有nodemanager的機器;

CP是單執行緒的,類似scp的模式,在執行速度上比DISTCP要慢很多。

5、提高dfs.datanode.du.reserved值

官網是這麼說的:Reserved space in bytes per volume. Always leave this much space free for non dfs use.

在上面的提到dfs.datanode.du.reserved的值是設成100G,因為namenode認為該節點還有剩餘的空間,所以給分配到這裡,假如這個塊是128K,但是實際剩餘空間只有100K,所以就會報上面的錯誤,假如把dfs.datanode.du.reserved成300G,讓namenode知道該節點已經沒有剩餘空間,所以就不會往這裡寫資料了。

6、關閉nodemanger程序

在現有計算資源多餘的情況下,可以考慮關閉高磁碟節點的nodemanager,避免在該節點起YarnChild,因為如果在該節點上進行計算的話,資料儲存首先會往本地寫一份,這樣更加加重了本地節點的負擔。

7、刪除舊資料

該方案是在迫不得已的情況下進行的,因為刪掉的資料可能以後還得補回來,這樣的話又是得要浪費一定的時間。

另外在刪除資料時候就得需要跳過回收站才能算是真正刪除,可以使用的命令如下:

三、方案選擇 考慮到有多達600臺機器磁碟使用率達到94%,而且這部分高的機器是在同一個機房的,所以不能採用上下節點的方法,最好的辦法如下: 1、提高dfs.datanode.du.reserved的值; 2、關閉nodemanager程序; 3、升降副本; 4、開啟原始碼的balance; 人工的定期觀察,當達到期望的效果的時候就是恢復成原樣;在提高dfs.datanode.du.reserved的值就得需要考慮到datanode需要進行輪詢的重啟,這個時候就考慮到時間間隔,如果時間過短就可能就丟,如果過長就是費的時間比較多。  這種方法好比:比如在節假日的時候,某個收費口的車輛特別多,那個時候執法人員就會封閉這個收費站的出口,等車輛過的差不多的時候再給開放。這次的方案有這個有點類似,當主機的dfs.datanode.du.reserved值高於目前磁碟使用的情況,namenode就不會分配資料過來了,通過升降副本和balance能快速的將本機的資料轉移走。 四、結束語

本篇文章主要介紹了對hadoop資料出現不均衡情況下可以使用的方案,並以例項來解決問題!

對此有興趣的同學歡迎一起交流 。