HDFS中hsync方法介紹
原創文章,轉載請注明:博客園aprogramer
原文鏈接:HDFS中hsync方法介紹
1. 背景介紹
HDFS在寫數據務必要保證數據的一致性與持久性,從HDFS最初的版本到2.0版本HDFS提供了兩種同步語義。
1. 將client端寫入的數據刷到每個DataNode的OS緩存中,如果每個副本所在的DataNode同時crash時(例如機房斷電)就會導致數據丟失(sync和hflush方法)。
2. 將client端寫入的數據刷到每個DataNode的磁盤中(hsync方法);
在Hadoop2.0和cdh4中DFSOutputStream提供了sync,hflush和hsync三個方法,sync和hflush均是語義1,而hsync是語義2,hsync比sync和hflush的同步性更強,下面詳細介紹hsync。
2. Hadoop2.0中hsync的語義
hsync的語義是:client端所有的數據都發送到副本的每個datanode上,並且datanode上的每個副本都完成了posix中fsync的調用,也就是說操作系統已經把數據刷到磁盤上(當然磁盤也可能緩沖數據);需要注意的是當調用fsync時只有當前的block會刷到磁盤中,要想每個block都刷到磁盤,必須在創建流時傳入Sync標示。
通過分析上面的語義,可以確定hsyn涉及到兩個角色client和DataNode,下面分別說明這兩個角色。
3. DFSClient端邏輯
DFSClient端邏輯主要包括以下幾步:
1. 判斷是否需要sync,如果當前的數據都已經sync到磁盤了,則不需要再次sync;判斷方法是首先調用flushBuffer(true),如果byteCurBlock(當前block的最后一個字節在file中的偏移量)大於上次sync的偏移量,則說明需要sync,否則不需要;
2. 如果需要sync,則將當前package的sync標示設為true;
3. 調用waitAndQueueCurrentPacket()將當前Package放到發送隊列中
4. waitForAckedSeqno()等待發送package的確認包
5. 如果當前block沒有調用namenode.fsync(),則調用該方法,持久化block元數據
6. 調用streamer.setHflush();
client端的時序圖如下所示

查看大圖:大圖
4.DataNode端處理邏輯
DataNode端的改動比較簡單,當接收的package的有sync標示,則執行flushOrSync
方法
(通過調用FileChannel的force方法,force方法會保證將文件內容刷到磁盤中)將block文件及meta文件刷到磁盤。序列圖如下:

查看大圖:大圖
5. 性能分析及改進
由於調用hsync會比較耗時,將來可優化的方向:
1. 不是每個副本的DataNode都執行hsync,只有一個DataNode執行hsync;
2. 不同機架上的DataNode執行hsync;
3. hsync可同步進行,而不是等待hsync完成之后再返回給client端response(在這種情況下,client端的hsync方法的返回並不確保sync的完成,只有datanode端能保證)
6. 參考資料
[2]. Hadoop2.0代碼
[3]. https://issues.apache.org/jira/browse/HDFS-744