HDFS的hflush,hsync和close有啥區別,分別做了什么
hflush: 語義是保證flush的數據被新的reader讀到,但是不保證數據被datanode持久化.
hsync: 與hflush幾乎一樣,不同的是hsync保證數據被datanode持久化。
close: 關閉文件.除了做到以上2點,還保證文件的所有block處於completed狀態,並且將文件置為closed
場景是寫一個字節(append或者create),然后調用hflush.看看hflush做了什么。
涉及到幾個線程,一個是調FSDataOutputStream的write的線程,它是應用程序自己的線程,write會將數據以packet的形式一個個的丟入data queue中。
另外兩個是HDFS客戶端代碼中的線程,其中一個是DataStreamer,負責從data queue中取出一個個的packet發出去,過程是為每個block建立一個pipeline,然后發packet,最后關閉pipeline,接着下一個block。另外一個是ResponseProcessor,負責處理下游節點的ack。
實際上,packet是由chunk組成的,每個chunk對應一個checksum,一個packet大概64KB左右,一個chunk通常512字節。通常情況下,每512字節算一個checksum,寫入到packet中。但是最后一個chunk通常是不滿512字節。hflush實際上,就是將最后不滿一個chunk的數據算checksum,然后
寫入packet,最后將這個packet放入data queue隊列.在我們只寫一個字節的場景下,一個字節不夠一個chunk,故data queue中始終每個packet,DataStreamer始終等待着沒有建立pipeline,調用hflush后,往data queue塞入一個packet,DataStreamer終於從data queue中取到一個packet,然后建立pipeline,接着發送packet。調完hflush的應用程序線程一直在等待最后一個packet的ack被收到,輪到ResponseProcessor上場。他不斷的處理從datanode收到的packet ack,不斷更新block的長度。接着,執行hflush的應用程序線程終於等到了最后一個packet的ack,然后它告訴namenode最后一個block的長度,namenode更新內存狀態,實際
上是根據文件名找到INodeFile,將block長度寫入,並且記一條edit log.
下面看看關閉文件close時做了什么.
FSDataOutputStream的close:
一開始也是和hflush一樣,將最后一個packet進data queue,不同的是還會生成一個特殊的packet入data queue,lastPacketInBlock標記設為true,意思是告訴datanode這是block的最后一個packet,然后等最后這個包的ack收到。接着關閉DataStreamer和ResponseProcessor線程。然后調用completeFile(),最后結束file lease.
看看completeFile():
通知namenode,namenode會做一些檢查:
- 根據文件名從目錄樹中拿出INode,檢查文件是否處於under construction狀態,如果不是,則complete file失敗.
- 從INode中拿出修改這個文件的lease holder和當前completeFile()這個客戶端比較,看是否是同一個client,如果不是,則complete file失敗(namenode從目錄樹中得到當前打開文件的信息,會定期檢查打開的文件的lease是否超過hard limit,默認1小時,如果超過了,會強行將文件的lease設置為namenode,這樣,client 就不能向namenode commit block了。)
- namenode會檢查文件的倒數第二個block是否已經是completed狀態,如果不是客戶端重試,否則,將最后一個block變成completed狀態,其實就是修改一下內存中數據結構,寫一條edit log。一個block是completed狀態的條件是滿足最低副本數要求,默認配置1,配置項DFS_NAMENODE_REPLICATION_MIN_KEY.當datanode收到一個block后,會向namenode匯報,只要有一個datanode匯報成功,namenode就將block置為completed.最后namenode將file置為closed狀態。
最后看看hsync.
實現上和hflush幾乎一樣,代碼共有,特殊的是最后一個packet標記為syncBlock狀態,datanode收到后就會落盤了.
參考資料
hadoop-hdfs-2.4.1.jar