大數據集群一個客戶端參數引起的任務性能差的問題
- 背景介紹
- 排查過程
- 任務慢的具體原因
- Executor中數據內存往磁盤溢寫
- 結果數據寫入分區路徑
- 分析
- 解決方案
- 結語&思考
背景介紹
隨著業務量不斷擴大,平臺逐步發展成HDFS多聯邦的架構,這個過程中,作為平臺維護人員也會對參數進行不定期的優化以應對逐漸繁重的存算壓力。
最近一個重點保障業務的計算任務無法滿足客戶的數據時延要求,客戶很生氣,然后也是各種投訴,然后項目上的同事就拉著一起查了下問題,最終定位到是一個客戶端參數在大體量集群下造成的,記錄一下
排查過程
在對日志進行分析的時候,主要發現了2個導致執行時間延長的點,分開進行說明:
任務慢的具體原因
在定位的時候,主要有2個地方會導致任務執行時間延長;
Executor中數據內存往磁盤溢寫
任務執行過程中,可能會看到下面的這種日志,這樣的日志一般是業務問題導致的,內存不夠用,臨時溢寫磁盤,但是對于一個執行時間達到幾個小時的任務來說,這個并不是主要的原因
結果數據寫入分區路徑
先看一個日志的關鍵截圖,首先是9:31分:
然后是12:25分的日志
上圖中可以看到在創建分區路徑到數據完全寫入完成度過了接近3個小時。
分析
因為可以基本定位到結果數據寫入分區路徑是主要影響任務時長的原因,所以對任務日志進行進一步排查,找找可能得原因;對比慢日志和快日志,有一個明顯區別:
// 執行速度比較快的任務日志
2025-03-19 11:35:16,253 INFO org.apache.hadoop.hive.common.FileUtils: Creating directory if it doesn't exist: viewfs://nsX/ns3/path/.hive-staging_hive_2025-03-19_11-35-16_251_7169943507895305206-1
// 執行速度比較慢的任務日志
2025-03-19 07:35:37,022 INFO org.apache.hadoop.hive.common.FileUtils: Creating directory if it doesn't exist: viewfs://ns0/spark-tmp/stagedir/.hive-staging_hive_2025-03-19_07-35-37_020_688260183047175897-1
這個是在執行計算任務的時候指定的數據臨時寫入的目錄路徑,如果任務提交節點的客戶端配置文件/etc/spark/conf/hive-site.xml
中沒有指定hive.exec.stagingdir
參數,最終hive-staging就會寫入到表對應的目錄下(這是默認行為)如果客戶端配置了這個參數,就會寫入到參數指定的目錄。
通過日志分析的結果,我們發現任務提交節點的客戶端配置配置了該參數的話,任務執行時間久的數量遠大于那些沒配置該參數的提交節點,對此我們進行了對比:
進一步分析下來,確定了問題邏輯,因為集群是聯邦環境,業務表可能存在于任意一個聯邦,如果配置了hive.exec.stagingdir
參數,任務執行時臨時數據就會寫入到一個指定的聯邦下,這個時候,如果結果表的路徑在其他聯邦,那么業務邏輯完成后,就會存在跨聯邦復制數據的動作;
而在跨 NameNode 執行 mv 操作時,會涉及到多個 NameNode 之間的元數據交互。源 NameNode 需要告知目標 NameNode 新文件的元數據信息,并且要確保兩個 NameNode 之間的數據一致性。這個過程涉及到網絡通信和同步操作,會增加額外的延遲,從而導致性能下降。
這就和我們在Linux上移動數據一樣,同一個磁盤移動(類比成同聯邦下)數據,只是元數據信息更改,不同磁盤移動數據(跨聯邦)數據,數據會存在塊寫入,就會產生大量IO,分布式集群還涉及到網絡等交互
解決方案
最終,我們決定刪除所有提交節點的hive.exec.stagingdir
配置項,這樣,任務提交的時候久采用結果表的同聯邦進行臨時數據的寫入,避免了跨聯邦的數據移動。
結語&思考
其實,對于普通HDFS集群,配置hive.exec.stagingdir
參數是很好的選擇,主要有這么幾個優點:
- 臨時文件寫在一個固定目錄,便于管理
- 任務失敗時不會主動刪除臨時文件,配置指定目錄能夠更方便的治理廢棄數據
然而,對于大型的聯邦集群,帶寬資源是珍貴的,我們應該盡量減少跨聯邦的數據交換,這個時候,保持原本的配置顯然就不太合理了,讓任務在執行時臨時數據寫在本聯邦下可能是更好的選擇,當然這帶來的問題就是更高的管理成本,以及定期的失敗任務臨時目錄治理需求