共計 9898 個字符,預計需要花費 25 分鐘才能閱讀完成。
這篇文章主要介紹“怎么處理 HDFS 問題”,在日常操作中,相信很多人在怎么處理 HDFS 問題問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么處理 HDFS 問題”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!
1. 定期 block 全盤掃描,引起 dn 心跳超時而脫離集群
hdfs 有一個目錄掃描機制,默認 6 小時會全盤掃描一次所有 block,判斷與內存里的那份 blockMap 是否一致。參考
https://blog.cloudera.com/hdfs-datanode-scanners-and-disk-checker-explained/
在小文件比較多的情況,掃描的時候特征很明顯——磁盤的 iops 很高,但吞吐量很低。當然這不是引起 datanode 心跳超時的原因,真正的原因是處理掃描后的結果,比如比較完發現有 20000 個 block 不一致,在修復這些 block 時不斷的持有了 FsDatasetImpl 這個對象的一把鎖,在磁盤比較慢的情況下,可能需要 5 分鐘甚至 10 分鐘處理完,從而一直阻塞讀、寫、心跳的線程。
詳細的可以了解 HDFS-14476 lock too long when fix inconsistent blocks between disk and in-memory,包括一些特征、證據,以及 block 修復邏輯,細節比較多。
解決辦法是,我們這邊加了個 patch(已合入 2.10 和 3.x),在處理異常 block 的時候,中間休息 2 秒,處理一下正常的請求,不至于 datanode 卡住甚至離線。
修復后的結果也是很明顯,datanode 心跳平滑了許多
2. namenode 遷移裁撤,遇到客戶端無法寫入
在文章 HDFS namenode 節點裁撤不停服遷移實踐 里總結了在線遷移 namenode 的方法。遷移 / 裁撤的思路是保持 namenode hostname 不變,滾動遷移 standby 的方式遷移。
但是在我們的遷移實踐中,發現 hdfs namenode 完成遷移后,集群正常,但 hdfs 客戶端訪問異常。在 yarn 這樣的長任務場景下,會導致文件讀寫一直失敗,直到 yarn nodemanager 重啟。
具體問題是這樣的:
client 使用的是 ConfiguredFailoverProxyProvider,client 啟動之后會根據當時的 inetsocket 創建 nn1,nn2 兩個 namenode proxy,這個在任何網絡異常的情況下都不會重新創建。
client 的 updateAddress 方法能檢測到 namenode ip 發生了變化,但由于那個異常沒有捕獲,本該在下次循環使用正確的 namenode ip 就能正常,但拋出異常后導致 client 重新連接 namenode,然而上面的 namenode proxy 還是舊地址,SetupConnection 異常,又進入 updateAddress 判斷邏輯,返回 true 又去建連接,陷入了死結。
復現步驟
打開一個 hdfsclient,長時間寫一個文件 hdfs put
更新 hdfs 新 namenode hostname-ip
stop old nn2, start new nn2
更新客戶端的 namenode hostname-ip (client 還在操作文件)
切換到新 namenode hdfs haadmin -failover nn1 nn2
此時會發現 client 一直報錯
在 yarn 客戶端啟動的周期內,哪怕是新文件寫入,依舊會報錯
對 ConfiguredFailoverProxyProvider 打了個 patch,就是在 client failover 之后,也進行 updateAddress 判斷,如果有 ip 變動,就重新 createProxy。驗證這個 patch 同樣有效。不過在 client 那邊統一捕獲會比較好,因為還有其他類型的 HaProvider 可能也有這個問題。
這個問題的 patch 已經被合入 Apache Hadoop 3.4,見 HADOOP-17068 client fails forever when namenode ipaddr changed。我們用的版本是 2.6.0-cdh6.4.11,也已合入。
除了從根源問題上解決,也可以在 namenode 遷移操作時,在老節點上啟用端口轉發,再逐個重啟 yarn,避免引起大范圍故障。
3. 集群 dn 不均衡導致文件寫入失敗
現象:集群將滿時,擴容了批機器緩解空間。運行了 2 個星期客戶端突然報文件寫入失敗
原因:hdfs 在部分 datanode 空間滿的情況下,理論會自動挑選其它可用的空閑節點。由于 dfs.datanode.du.reserved 配置不當,導致依然會選中滿節點。具體是 dfs.datanode.du.reserved 如果小于分區 block reserved,在磁盤用滿時就會出現
org.apache.hadoop.ipc.RemoteException(java.io.IOException): File
/kafka/xxxtmp.parquet could only be replicated to
0 nodes instead of minReplication
(=1). \
There are
14 datanode(s) running
and no node(s) are excluded
in this operation.
解決:
擴容完,跑 rebalance
修改磁盤分區的 block reserved,使其小于 dfs.datanode.du.reserved. 見 hdfs datanode Non DFS Used 與 Remaining .
增加單個 datanode 容量告警
4. 做 rebalance 時速度很慢
啟動 rebalance 命令./start-balancer.sh -threshold 10,如果需要提高速度可以修改限流帶寬 hdfs dfsadmin -setBalancerBandwidth 52428800
但是 datanode 上同時接收 blocks 并發數,是不能在線調整的(或者說只能調小),調整 hdfs-site.xml 默認的 balance 參數,并重啟
dfs.balancer.moverThreads=1000
dfs.balancer.dispatcherThreads=200
dfs.datanode.balance.max.concurrent.moves=50
如果啟動 balance 時,嘗試以更高的并發執行,datanode 會判斷沒有足夠的線程接收 block: IOException: Got error, status message Not able to copy block … because threads quota is exceeded。
當 move 出現失敗時,遷移速度是指數級下降的,因為 move block 失敗默認會 sleep 一段時間。
./start-balancer.sh
-threshold
5\
-Ddfs.datanode.balance.max.concurrent.moves=20 \
-Ddfs.datanode.balance.bandwidthPerSec=150000000 \
-Ddfs.balancer.moverThreads=500 \
-Ddfs.balancer.dispatcherThreads=100
5. 給 datanode 在線增加磁盤
騰訊云上的機器,可以直接在原有 datanode 上直接掛在新的磁盤,快速給 hdfs 擴容。
增加磁盤,不需要重啟 datanode。(前提是設置了 dfs.datanode.fsdataset.volume.choosing.policy 為 AvailableSpaceVolumeChoosingPolicy)
掛載后,先建立 hadoop 數據目錄并修正權限
在 hdfs-site.xml 里加上新目錄配置 dfs.datanode.data.dir
可以使用 reconfig 命令使其生效: hdfs dfsadmin -reconfig datanode dn-x-x-x-x:50020 start
6. namenode 設置了 HA,但故障時未成功切換
現象:active namenode 內存故障,主備切換失敗
原因:dfs.ha.fencing.methods 設置為了 ssh,但是并不能登錄其他 namenode 執行 fence
解決:生成 ssh key,免密碼登錄。或者改成 shell(/bin/true),強切。注意,修改 fence 方式后,需要重啟 zkfc。
7. hdfs client input/output error
現象:執行 hdfs 客戶端命令報錯 input/output error,試著拷貝 hadoop / jdk 的介質目錄,亦發現文件損壞。有時會發現 jvm core
原因:磁盤存在壞塊,剛好 hdfs 或者 jdk 的 jar 庫損壞。通過觀察 messages 發現有 sda IO Input/Output Error
使用 badblocks -s -v -o bb.log /dev/sda 可以看到磁盤損壞了哪些扇區
解決:從其他機器,拷貝一份正常的介質
8. hdfs 誤將 data 盤作為數據盤
誤將系統盤作為了 dfs.datanode.data.dir,運行一段時間后,這個分區很容易最先滿。
這個是配置上的問題,理解 datanode 的工作方式,可以快速的將這個分區里的 block 挪到正確的磁盤分區。
處理方法就是停止 datanode,拷貝 /data block 到其它分區,刪掉 /data 的配置。因為 datanode 上 block 的位置是每次啟動的時候,掃描上報給 namenode,所以可以做物理拷貝。
可以使用拷貝命令 cp -a /data/hadoopdata/current/BP-*-*/current/finalized/* /data1/hadoopdata/current/BP-*-*/current/finalized/ ,不能拷貝整個 hadoopdata 目錄,因為 VERSION 文件里面的 storageID 不同。
9. 使用 decomiss 方式將 datanode 退服時,客戶端讀寫異常
現象:將 datanode 加入 exclude,正常 decomissing 的方式退役節點,應用層反饋 spark 任務部分異常,報錯 Unable to close file because the last block doest not have enough number of replicas ,但該集群一些其它的文件讀寫任務正常。
原因:spark 任務會頻繁的創建、刪除 application 目錄。在 decomissing 時,部分磁盤性能低的節點,磁盤更加繁忙,導致出現 last contact 心跳時間長
解決:經過驗證,發現直接 kill datanode 進程的方式,不影響 spark 任務。但必須保證一個一個的 kill,否則會出現 missing block.(這不一定是解決問題最好的辦法,但的確有效)
10. namenode editlog 長時間未做 checkpoint
standby namenode 的一個作用是,定期合并從 journalnode 上獲取的 editlog,生成新的元數據 fsimage,然后推送到 active namenode。
當 standby namenode 出現異常,如進程退出、軟件 bug(比如我們遇到過 IOException: No image directories available!),導致長時間未合并 editlog。一旦需要發生切換或者重啟 namenode,有可能導致啟動時間過長,嚴重的 editlog 合并需要的內存不足,無法啟動 namenode.
如果內存不足,一種解決辦法是借一臺高內存臨時機器合并 editlog:
把 standby 停下來,將 hdfs 的軟件介質和配置文件,拷貝到高內存機器
同時拷貝 dfs.namenode.name.dir 目錄中最新能用的 fsimage_xxx 和它之后的所有 edits_xxx-xxx
在臨時機器上啟動 namenode 進程,會自動從對應目錄加載 fsiamge、合并 editlog
預防比補救要重要,一定要監控 namenode 上 TransactionsSinceLastCheckpoint 這個指標,我們的閾值是達到 5000000 就告警。
11. HDFS 3.x datanode 出現大量 CLOSE-WAIT
這個問題 HDFS-15402 是在定期對 datanode http://127.0.0.1:50075/jmx jmx 進行探測的時候產生的,我們有 5 個 hadoop 3.1.3 的集群都存在該問題。在 hadoop 2.x 中正常。
50075 端口上產生過多 close-wait 的影響是,正常的 webhdfs 會出現 504 Gateway-timeout
[root@dn-9-4-xxx-yy
/tmp]# ss -ant|grep :50075 |grep CLOSE-WAIT|wc -l
16464
[root@dn-9-4-xxx-yy
/tmp]# ss -ant|grep :50075 |grep CLOSE-WAIT|head -3
CLOSE-WAIT
123 0 9.4.xxx.yy:50075
9.4.xxx.yy:39706
CLOSE-WAIT
123 0 9.4.xxx.yy:50075
9.4.xxx.yy:51710
CLOSE-WAIT
123 0 9.4.xxx.yy:50075
9.4.xxx.yy:47475
lsof
-i:39706
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 134304 hdfs
*307u IPv4 429yy7315 0t0 TCP dn-9-4-xxx-yy:50075- dn-9-4-xxx-yy:39706 (CLOSE_WAIT)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 123 0 9.4.xxx.yy:50075 9.4.xxx.yy:39706 CLOSE_WAIT 134304/java
CLOSE-WAIT 狀態是客戶端 (curl) 發起關閉 tcp 連接時,服務端 (datanode) 收到了 FIN-ACK,但在關閉 socket 時一直沒有完成。正常流程是關閉 socket 完成,然后向客戶端發送 FIN
所以問題出在 datanode server 上,與 knox 還是 haproxy 客戶端沒有關系。并且這個問題調整 os 內核參數是沒有用的,除非 kill datanode,否則 close-wait 狀態會永久存在。使用網上的 kill_close_wait_connections.pl 能夠清理這些 close-wait,之后 webhdfs 請求變得好轉。
目前避開的方法就是,不再請求 datanode jmx 做監控,只獲取 namenode 上的指標。datanode 上采集 os 級別的指標。
12. knox 無法上傳 8G 文件
在官方 jira 里我們提了這個問題 KNOX-2139,當我們使用 webhdfs with knox 上傳 8589934592 bytes 大小的文件,會出現 (55) Send failure: Broken pipe,在 hdfs 只能看到一個空文件。而且在版本 knox 1.1, 1.2 中是必現,在 0.8 版本正常。
簡單 debug 了一下代碼,knox 拿到的請求 contentLength 為 0,8G 以外的情況 contentLength 為 -1。
我們后來使用 haproxy 代替 knox 解決 knox 自身上傳速度慢和這個 8G 文件的問題。在 備份系統上傳優化:從 knox 到 haproxy 有介紹我們的實現
不過在最新的 1.4 版本,8G 問題又消失了。根據官方的恢復,可能跟 jetty 的升級有關。
13. Unable to load native-hadoop library for your platform
Unable to load native-hadoop library for your platform… using builtin-java classes
經常在執行 hdfs 客戶端命令時會有這樣的提示,其實是個老生常談的問題。
簡單說就是系統里沒有找到原生的 hadoop 庫 libhdfs.so,這個庫是 C 寫的,性能比較好。缺少但不影響使用,因為 hadoop 里有 java 實現的客戶端庫。
出現這個我總結原因有 3 個:
hadoop 安裝包里沒有自帶 libhdfs.so
這個情況占很大一部分。去到目錄 ${HADOOP_HOME}/lib/native/,看下是否有 libhdfs.so,libhdfs.a,libhadoop.so,libhadoop.a。如果沒有的話,可以重新下一個完整的二進制包,把 lib/native 拷出來用
這種看到才是正常的
./bin/hadoop checknative
20/05/14 20:13:39 INFO bzip2.Bzip2Factory: Successfully loaded
initialized native-bzip2 library system-native
20/05/14 20:13:39 INFO zlib.ZlibFactory: Successfully loaded
initialized native-zlib library
Native library checking:
hadoop: true
/data1/hadoop-hdfs/hadoop-dist/target/hadoop-2.6.0-cdh6.4.11-tendata/lib/native/libhadoop.so.1.0.0
zlib: true
/lib64/libz.so.1
snappy: true
/data1/hadoop-hdfs/hadoop-dist/target/hadoop-2.6.0-cdh6.4.11-tendata/lib/native/libsnappy.so.1
lz4: true revision:10301
bzip2: true
/lib64/libbz2.so.1
openssl: true
/usr/lib64/libcrypto.so
實在不行就在自己的 os 上編譯一個。
mvn clean package
-Pdist,native
-DskipTests
-Dtar
-Dbundle.snappy
-Dsnappy.lib=/usr/local/lib
so 文件存在,但路徑不對
現在的版本,默認路徑都能找得到 so 庫。這個 Hadoop“Unable to load native-hadoop library for your platform”warning 里面介紹的大部分方法,都是在教怎么設置路徑。真實原因很少會因為路徑不對,不過這個答案靠譜 https://stackoverflow.com/a/30927689 ,也就是我們的情況 3
編譯的版本,在我們的 os 上依賴庫不全
遇到過這種,glibc 庫版本不夠:
$ ldd lib/native/libhadoop.so
lib/native/libhadoop.so: /lib64/libc.so.6: version `GLIBC_2.14
not found
(required by lib/native/libhadoop.so)
linux-vdso.so.1 = (0x00007ffd1db6d000)
/$LIB/libonion.so
= /lib64/libonion.so
(0x00007f5bfd37d000)
libdl.so.2 = /lib64/libdl.so.2 (0x00007f5bfce40000)
libpthread.so.0 = /lib64/libpthread.so.0 (0x00007f5bfcc23000)
libc.so.6 = /lib64/libc.so.6 (0x00007f5bfc88f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5bfd266000)
$ strings
/lib64/libc.so.6 |grep GLIBC_
可以看當前系統支持哪些版本的 glibc
但是 glibc 安裝升級有風險,如果要安裝 2.14 版本務必先做好測試。
14. 處理 missing blocks
hdfs 集群出現 missing block,無非就是 namenode 里還記錄的 block 元數據信息,但是所有副本都丟失了。如果是同時掛了多個機器,或者損壞了多個機器上的磁盤,是有可能會出現。
遇到過 2 次人為產生 missing blocks:
kill 一個 datanode 進程,就出現 missing block
先設置所有文件的 replication 為 1,一小段時間后,再設置為 2
這兩種情況都算是 bug,對應的文件確實無法 get 下來了。但第 1 中情況還好,經過排除日志,發現實際這些丟失的 blocks 本就接收到了刪除命令,過一段時間后,missing block 一般會自動消失。第 2 中情況,是真的意外丟 block 了,比較嚴重。不要輕易把 replication 設置為 1,再改回去可能丟 block。
如果確認這些 missing block 可以消除,可以通過 fsck 命令手動處理:
// 如果 missing blocks 數不是很多,可以直接逐個 delete
hdfs fsck file_name
-delete
// 如果 missing blocks 較多,可以從 namenode 上拿到 corrupt 塊
hdfs fsck
/ -list-corruptfileblocks
-openforwrite
| egrep
^\.+$ | egrep
MISSING|OPENFORWRITE | grep
/[^]* | sed
s/:$// missing_blocks.txt
15. 應該關注的告警
實際還有些許多問題,比如用戶 supergroup 權限問題、rack-aware.sh 文件缺失的問題,限于篇幅就不列舉了。
問題是不斷會出現的,但及時對大部分場景做到監控工具,能夠提前發現問題。下面是整理并上線的關鍵告警指標:
datanode lastcontact
datanode 與 namenode 心跳監控。心跳時間長意味這這個 dn 沒響應了,默認超過 10m30s 沒響應,dn 會脫離集群。
namenode and datanode web probe
namenode 50070 與 datanode 50075 從外部探測,并且 datanode 會根據 include 里面的地址自動增減。我們使用修改過了 telegraf http_response 插件, 支持動態讀取 url,比如 exec bash get_datanode_urls.sh
dirctory max files
單目錄下的文件數告警。hdfs 默認限制單目錄下最大的文件數 100 萬,由配置項 dfs.namenode.fs-limits.max-directory-items 決定。
這個指標數據來源于 fsimage 目錄畫像分析。
transactions not merged
standby 未滾動的 editlog 數。長期未 checkpoint 會導致下次 namenode 啟動消耗過多內存,甚至啟動失敗。
missing blocks
異常 blocks 數
test write file
在 2 個 namenode 節點上,定期使用 hdfs put/get 寫入文件。如果失敗會告警
non-active namenode
hdfs 集群 namenode 有且只有一個 active,一個 standby。其它情況告警
cluster capacity
集群總體容量監控
node usage, ioutil
單個 datanode 磁盤空間使用率預警,ioutil 持續 5 分鐘大于 95% 預警。
failover occurs
hdfs namenode 發生 failover
namenode heap size
namenode heap size 使用比率。blocks 數量多,內存使用越多。
到此,關于“怎么處理 HDFS 問題”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!