hadoop 一致性模型,確保斷電不丟數據(hflush() 和 hsync())

原文鏈接:https://www.infoq.cn/article/large-data-processing-ensuring-data-not-lost-when-power-off

在 Hadoop 2.0.2-alpha 之前,HDFS 在機器斷電或意外崩潰的情況下,有可能出現正在寫的數據丟失的問題。而最近剛發佈的 CDH4 中 HDFS 在 Client 端提供了 hsync() 的方法調用 ( HDFS-744 ),從而保證在機器崩潰或意外斷電的情況下,數據不會丟失。這篇文件將圍繞這個新的接口對其實現細節進行簡單的分析,從而希望找出一種合理使用 hsync() 的策略,避免重要數據丟失。

HDFS 中 sync(),hflush() 和 hsync() 的差別
在 hsync() 之前,HDFS 就已經提供了 sync() 和 hflush() 的調用,單從方法的名稱上看,很難分辨這三個方法之間的區別。咱們先從這幾個方法之間的差別介紹起。
在 HDFS 中,調用 hflush() 會將 Client 端 buffer 中的存放數據更新到 Datanode 端,直到收到所有 Datanode 的 ack 響應時結束調用。這樣可保證在 hflush() 調用結束時,所有的 Client 端都可以讀到一致的數據。HDFS 中的 sync() 本質也是調用 hflush()。

hsync() 則是除了確保會將 Client 端 buffer 中的存放數據更新到 Datanode 端外,還會確保 Datanode 端的數據更新到物理磁盤上,這樣在 hsync() 調用結束後,即使 Datanode 所在的機器意外斷電,數據並不會因此丟失。而 hflush() 在機器意外斷電的情況下卻有可能丟失數據,因爲 Client 端傳給 Datanode 的數據可能存在於 Datanode 的 cache 中,並未持久化到磁盤上。下圖描述了從 Client 發起一次寫請求後,在 HDFS 中的數據包傳遞的流程。


hsync() 的實現本質
hsync() 執行時,實際上會在對應 Datanode 的機器上產生一個 fsync 的系統調用,從而將內存中的相關文件的數據更新到磁盤。

Client 端執行 hsync 時,Datanode 端會識別到 Client 發送過來的數據包中的 syncBlock_ 字段爲 true,從而判定需要將內存中的數據更新到磁盤。此時會在 BlockReceiver.java 的 flushOrSync() 中執行如下語句:

((FileOutputStream)cout).getChannel().force(true);

而 FileChannel 的 force(boolean metadata) 方法在 JDK 中,底層爲於 FileDispatcherImpl.c 中調用 fsync 或 fdatasync。metadata 爲 true 時執行 fsync,爲 false 時執行 fdatasync。

Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this, 
jobject fdo, jboolean md)
{
    jint fd = fdval(env, fdo);
    int result = 0;

    if (md == JNI_FALSE) {
        result = fdatasync(fd);
    } else {
        result = fsync(fd);
    }
    return handle(env, result, "Force failed");
}

當 Datanode 將數據持久化到磁盤上後,會發 ack 響應給 Client 端。當收到所有 Datanode 的 ack 響應時,hsync() 的調用結束。

值得注意的是,fsync 或 fdatasync 本身是一個非常耗時的調用,因爲磁盤的讀寫速度遠低於內存的讀寫速度。在不調用 fsync 或 fdatasync 的情況下,數據可能保存在各級 cache 中。

最開始筆者在測 hsync() 的讀寫性能時,發現不同機器上測試結果 hsync() 耗時差別巨大,有的集羣平均調用耗時爲 4ms,而有的集羣平均調用耗時則需 25ms。後來在公司各位大神的點撥下才意識到是跟 Linux 文件系統的機制有關。在這種情況下,只有一探 Linux 相關部分的源碼才能解開心中的疑惑,下面這節就將從更底層的角度來解析與 hsync() 密切相關的系統調用 fsync 及 fdatasync 方法。

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