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