自動化HDFS數據清理的終極方法(附代碼)

代碼地址:https://github.com/lijufeng2016/data-manager

一、背景

hdfs集羣從出生到成長,經歷了各種各樣業務和人的摧殘,早已疲憊不堪,承受巨大壓力。某天,你突然發現hdfs的空間超過80%的告警閾值,這時候,你的第一反應是找出那些比較佔空間的目錄,手動刪除,或者是寫個定時腳本每天清理固定的目錄,隨着業務和時間的不斷摧殘,小朋友,你是否有很多問號?

  • 佔大頭的文件清理後還是發現hdfs佔用空間大,不停地找要清理的目錄,最後發現小文件加起來也佔用大
  • 同時很多人使用同一個集羣,經過互聯網的幾番大洗禮後hdfs留下很多已離職人員的大量文件不知所措
  • 哪些數據該清還是不該清毫無頭緒,萬一誤刪了呢
  • 很多垃圾文件存放在hdfs上,但是分不清哪些到底是垃圾文件,不知道文件還有沒有人用

針對上述問題,我們可不可以換一種清理hdfs的思路呢?不需要反覆修改腳本去指定特定要刪的目錄呢?也不需要爲了找哪些需要清理的目錄而焦頭爛額呢?我給你換種思路。

二、原理

本文介紹一種方法,可以清hive數據,也可以清非hive表的hdfs數據。基本原理是通過解析hadoop fsimage文件獲得hdfs全量的文件路徑和所有文件最後的訪問時間,請hive表數據則還需要加上hive的元數據信息。

fsimage:

fsimage是hdfs的心臟,hdfs的全量的路徑信息都存放在fsimage文件裏面。我們在操作hdfs時,不論是增刪改查,hadoop都會記錄一條edit log,也就是hdfs的操作記錄,edit log會定時merge生成fsimage文件,在HA模式下,fsimage文件由standby NameNode生成,單點模式下,由secondary NameNode生成。fsimage文件本身是二進制不可明文讀取的,我們需要解析成可讀的形式,比如csv。hadoop自帶的命令hdfs oiv是專門用來解析fsimage文件,通過執行hdfs getconf -confKey dfs.namenode.name.dir命令可以知道fsimage的路徑,在路徑下默認會保存兩個fsimage文件,都是fsimage_xxxxxxxxxxx的格式帶一串時間戳,時間戳最大的那個就是由最新edit log合併解析生成的。

執行:

hdfs oiv -p Delimited -delimiter "," -i fsimage_xxxxxxxx -o fsimage.csv

解析fsimage生成csv文件,文件內容包含了hdfs所有文件和目錄,csv包含如下列:

  • Path 目錄路徑
  • Replication 備份數
  • ModificationTime 最後修改時間
  • AccessTime 最後訪問時間
  • PreferredBlockSize 首選塊大小 byte
  • BlocksCount 塊 數
  • FileSize 文件大小 byte
  • NSQUOTA 名稱配額 限制指定目錄下允許的文件和目錄的數量。
  • DSQUOTA 空間配額 限制該目錄下允許的字節數
  • Permission 權限
  • UserName 用戶
  • GroupName 用戶組

加粗的部分,是兩個最重要的字段,AccessTime作爲hdfs文件訪問的最後時間,可以根據它去確定哪些文件還在用,哪些已經很久沒用,可以判定爲垃圾文件或過期數據,達到清理的目的。必須要開啓dfs.namenode.accesstime.precision參數纔會有AccessTime,默認開啓值爲1。但是在hdp集羣是默認關閉的,注意要在hdfs-site.xml文件裏面配置開啓。

解析後的csv文件會上傳到對應字段的建好的hive表,給後面清理邏輯使用

hive元數據

一般在配置hive的時候,都會選用mysql作爲元數據存儲的介質,hive的元數據表很多,記錄了表名、分區、路徑、參數等等一切除了表數據之外的所有信息,我們在hive的元數據庫裏面需要知道表的hdfs路徑分區,清理hive數據的時候再根據上述的fsimage對應的hive表去做關聯,把要清理的表或表分區關聯出來

三、使用方法

代碼地址:https://github.com/lijufeng2016/data-manager

主類:

com.xkj.mlrc.fsimage.GenerateFsimageTable:解析生成fsimage的csv文件並上傳到hive

com.xkj.mlrc.clean.table.HiveTableClean:清理hive表的邏輯,分區表則清分區,非分區表則刪表

com.xkj.mlrc.clean.file.HdfsFileClean:清理hdfs目錄文件的邏輯,與上面清理hive的邏輯獨立不衝突

args參數說明:

參數名 說明
-targetPath 指定的要刪的目標路徑,逗號隔開
-avoidPath 要避開刪除的路徑,不掃描的路徑,逗號隔開
-avoidSuffix 要避開的包含後綴的文件,逗號隔開
-avoidPrefix 要避開的包含前綴的文件,逗號隔開
-avoidDbs 要避免刪除的hive庫,包含庫下所有的表分區,逗號隔開
-avoidTbls 要避免刪除的hive表,包含表下所有的分區,逗號隔開
-avoidTbls-file 用要避免刪除的表,用文件存放在hdfs,必須是“庫.表名”的形式,包含表下所有的分區
-expire 過期的數據時間,也就是清理多少天沒有讀取過的hdfs數據,這是個參數很重要,必須大於0
-hdfsroot hdfs根路徑,HA模式如 hdfs://bigdatacluster,單點模式如:hdfs://xxxx:50070

必要的準備

本地idea運行:

step1:準備工作

必須要把hive-site.xml、core-site.xml、hdfs-site.xml文件放在項目的resources下,否則運行不起來!然後按照自己的環境修改所有config.properties配置項。

step2:解析fsimage文件

執行主類com.xkj.mlrc.fsimage.GenerateFsimageTable,會遠程ssh到NameNode執行一系列shell並解析fsimage文件上傳到hdfs

step3:清理數據

根據自己的需要運行

com.xkj.mlrc.clean.table.HiveTableCleancom.xkj.mlrc.clean.file.HdfsFileClean清理hive表或hdfs數據,並根據上面的args參數說明列表傳入自己需要的參數運行

yarn運行:

step1:準備工作

照自己的環境修改所有config.properties配置項,maven打包項目生成data-manager.jar文件上傳到集羣機器上

step2:解析fsimage文件

執行項目run目錄下的ParseFsimageFile2Hive.sh腳本,會遠程ssh到NameNode執行一系列shell並解析fsimage文件上傳到hdfs

step3:清理數據

根據自己的需要運行項目run目錄下的HdfsFileClean.shHiveTableClean.sh腳本清理hive表或hdfs數據,根據自己的需要配置上面的args參數列表

四、總結

這種方法完美的利用了fsimage文件和hive元數據。傳統刪數據的方法需要用戶知道哪些目錄該刪或不該刪,用這種方法,你只需要關注多久沒使用過的數據就刪,比如有的文件連續超過7天未被讀取,之後被讀取的可能性也不大,就可以用上面的代碼去做清理。代碼裏也特意做了安全機制,hdfs的java api中,直接刪除的話不會放hdfs的回收站,會直接永久刪除,這個項目裏是把所有數據放入回收站,等到回收觸發的時間才徹底刪除,如果誤刪了數據也可以有時間恢復。歡迎star 本項目!!

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