最近測試Hadoop數據一致性,發現Hadoop SequenceFile BLOCK壓縮類型(io.seqfile.compression.type=BLOCK)的文件存在數據丟失狀況,對此進行研究並解決。算法
先來了解SequenceFile BLOCK壓縮類型的數據寫入機制:緩存
BLOCK壓縮類型的SequenceFile數據結構圖數據結構
BLOCK壓縮類型的SequenceFile.Writer實現類爲SequenceFile.BlockCompressWriter,寫入流程以下:oop
1.寫入頭部信息:版本信息,壓縮類型信息,壓縮算法類信息,keyClass/valueClass類名,Metadata等;測試
2.寫入Sync標記;spa
3.將key和value序列化並寫入緩存,當緩存大小達到閾值(默認io.seqfile.compress.blocksize=1000000字節),觸發sync()操做,sync操做:先寫入sync標記,再將緩存中的key和value進行壓縮寫入FSDataOutputStream,格式如上圖中的Block compression。 這樣就成功寫入了一個block;it
4. 後續的數據寫入流程和3同樣;io
5. 當最後數據寫入完成後,會存在最後一個block的數據小於io.seqfile.compress.blocksize,這樣不會觸發sync()操做,因此必須調用BlockCompressWriter的close()方法,其中會去調用sync()操做將最後剩餘的數據寫入FSDataOutputStream,並對FSDataOutputStream作close(),至此完成整個寫入流程。file
解決個人問題:
序列化
個人問題是因爲在寫入數據結束後只對FSDataOutputStream作了close()操做,而根據BLOCK壓縮類型的寫入必須調用Writer的close()操做,才能觸發sync()操做將剩餘數據壓縮寫入FSDataOutputStream。而在個人實現中,當設置io.seqfile.compression.type爲NONE和RECORD,不會出現數據丟失。 由於這兩種壓縮類型,是來一條數據就寫入outputStream,沒有BLOCK這樣的緩存後再寫入機制。