HDFS DataNode掃描機制及相關參數

  衆所周知,HDFS中數據都是保存在DataNode中,通過複製相同的數據到多個DN中,HDFS可以容忍DN的失敗。但如果某些DN的磁盤出現故障,會怎麼樣呢?本文解釋了DN上的一些後臺任務是如何工作的,以幫助HDFS跨多個DN管理其數據以實現容錯。特別地,將重點介紹Block Scanners & Volume Scanners, Directory Scanners 以及 Disk Checker:它們做什麼,如何工作及一些相關的配置。

HDFS中的Block

  在詳細介紹DataNode 掃描器(或檢查器)之前,我們先簡要說明一下HDFS中的block的組織結構,重點說明DataNode中的block組織結構。我們知道,HDFS中的整體架構中,NameNode(NN)存儲的是元數據(metadata),而DataNode(DN)存儲的是實際的數據。通常,每個DN都是有多塊數據盤(HDFS的術語稱之爲volume)的。HDFS中的一個文件是由一個或多個block組成,每個block有一個或多個拷貝(稱爲Replica,副本),同一個block的不同副本存儲在不同的DN上。每個block的詳細狀態都通過block report從DN發送給NN。一個block會有多種狀態,一個處於finalized狀態的block最終會以block文件和meta文件存儲在DN磁盤上的本地文件系統中。其中block文件存儲文件數據,而meta文件存儲的是文件數據的校驗和,用以驗證block文件的完整性。meta文件以block文件命名,同時包含一個生成戳。下圖是一個DN磁盤的block文件和他們的meta文件的示例:
在這裏插入圖片描述
  HDFS的核心假設之一是,硬件故障是一種常態,而不是例外。當磁盤出現故障時,block文件和meta文件都可能會損壞。HDFS有識別和處理這些問題的機制。這些機制是什麼?特別地:

  • DN是在什麼時候以及如何驗證一個block?
  • DN如何驗證其內存中關於block的元數據是否與磁盤上的實際數據一致?
  • 如果在block讀取期間發生故障,是由於磁盤錯誤?或者只是一些間歇性錯誤(如網絡超時)?

  這些問題的答案存在於DN後臺的各種任務中,這就是接下來要介紹的。下面將會介紹DN上的三種任務,每種任務都試圖相應地解決上面的一個問題:Block Scanners & Volume Scanners, Directory Scanners 以及 Disk Checker。

Block Scanner & Volume Scanner

  Block Scanner的功能是掃描block數據以檢測可能的損壞。由於在任何時間任何DN上的任何block都可能發生數據損壞,因此及時發現這些錯誤是很重要的。這樣NN可以刪除這些損壞的block並重新複製它們,以確保數據的完整性以及減少客戶端的錯誤。這樣磁盤I/O仍然可以滿足實際的請求。
  因此,Block Scanner需要以相對比較低的頻率並相對快速的確保那些可疑的block被掃描,並且每隔一段時間掃描一次其他的block,同時不消耗大量的I/O資源。
每個DN都有一個Block Scanner與其關聯,同時Block Scanner會包含一組Volume Scanner的集合。每個Volume Scanner會運行自己的線程並負責掃描DN上的單個volume。Volume Scanner會慢慢的逐個讀取所有的block,並驗證每個block。我們稱之爲常規掃描(regular scan)。注意,這些掃描會非常慢,因爲執行檢查需要讀取整個block,這會消耗大量的I/O。
  Volume Scanner還維護了一個可疑block的列表。從磁盤讀取這些block時會導致一些特定類型的異常拋出。掃描過程中,可疑block的掃描會優先於常規block。此外,每個Volume Scanner都會跟蹤它過去十分鐘掃描過的可疑block,避免重複掃描。
  注意,Block Scanner和Volume Scanner是實現細節,他們一起處理block掃描的工作。因此簡單起見,我們將在後面的部分統一將Block Scanner和Volume Scanner稱爲 ‘Block Scanner’ 。

  Block Scanner是通過如下的機制來決定要掃描的block:

  • 當一個DN爲來自客戶端或者另一個DN的I/O請求提供服務時,如果發生了IOException,並且不是由於網絡原因(如socker超時、管道斷開或連接重置)造成的,那麼該block就會被標記爲可疑的(suspicious)並將其添加到Block Scanner的可疑block列表中
  • Block Scanner會在所有block上循環,每次迭代會掃描一個block
    • 如果可疑block列表不爲空,就會彈出一個可疑block進行掃描;
    • 否則,會掃描一個正常的block

   只有本地(非網絡)IOException會導致block被標記爲可疑的,因爲我們希望保持可疑block列表的簡短並減少誤報。這樣,一個損壞問題就會優先得到處理並及時報告。
   爲了跟蹤block之間的掃描位置,會爲每個volume維護一個block cursor。cursor會週期性的保存到磁盤中。這樣,即使DN進程重啓或服務器重啓,掃描也不必從頭重新啓動。
   下圖是一個 block cursor文件的示例:
在這裏插入圖片描述
   如本節開頭提到的,scanner的另一問題是I/O的消耗。無論被掃描的block是可疑block還是正常block,我們都不能持續的循環掃描它們,因爲這可能造成繁忙的I/O並損害正常的I/O性能。爲了解決此問題,scanner以可配置的速率運行,兩次掃描週期之間會有適當的睡眠時間。掃描週期是執行整個掃描的間隔時長。當一個block被標記爲可疑時,如果volume scanner正在等待下一個掃描週期,則會被喚醒。如果在掃描期間內未完成一次完整掃描,則掃描將繼續而不會休眠。

   Block Scanner相關的配置如下:

  • dfs.datanode.scan.period.hours 如果爲正值,則數據節點在指定的掃描週期內不會掃描任何單個塊多次。如果爲負,則禁用Block Scanner。如果設置爲零,則使用默認值504小時或3周,默認是504。以前版本的HDFS描述的將此值設置爲0將禁用Block Scanner的說法是錯誤的。
  • dfs.block.scanner.volume.bytes.per.second 如果爲0,則將禁用DataNode的塊掃描程序。如果爲正值,則這是DataNode的Block Scanner嘗試每秒從每個volume中掃描的字節數,默認是1048576,也就是1MB。

Directory Scanners

   雖然Block Scanner可以確保存儲在磁盤上的block文件處於良好狀態,但DN將block信息緩存在內存中。因此,確保緩存信息的準確性至關重要。Directory Scanner將會檢查並修復緩存和磁盤中實際數據之間的不一致。Directory Scanner會定期掃描數據目錄中的block和metadata文件,並使磁盤和內存中維護的block信息之間的差異保持一致。
   如果一個block被標記爲corrupted,它將通過下一個block report報告給NN。然後,NN將安排block從完整的副本進行復制。
   與Block Scanner類似,Directory Scanner也需要限制。限制是通過爲每個Directory Scanner線程指定每秒只能運行的毫秒數來實現的。

   Directory Scanner相關的配置如下:

  • dfs.datanode.directoryscan.interval DataNode掃描數據目錄並協調內存塊和磁盤塊之間的差異的間隔時間(秒)。支持多種時間單位,默認21600s(6小時)。
  • dfs.datanode.directoryscan.threads Directory Scanner並行執行時的線程數,默認是1。
  • dfs.datanode.directoryscan.throttle.limit.ms.per.sec 指定每秒中Directory Scanner線程運行的毫秒數。限制是針對每個線程的,不是聚合的。如爲4個compiler 線程設置100ms的限制,表示每個線程都限制爲100ms,而不是每個線程限制爲25ms。注意,限制不會中斷 report compiler thread,因此線程每秒的實際運行時間通常會比限制稍高一些,通常不會超過20%。值只有介於1和1000之間纔有效,設置無效的值將導致禁用限制並記錄錯誤消息。默認是1000毫秒,也就是禁用compiler線程限制。

Disk Checker

  除了上面提到的scanner以外,DN還會在後臺線程中運行一個Disk Checker,以確定volume是否不健康以及是否要將其刪除。使用Disk Checker的原因是,如果在volume級別出現問題,HDFS應該檢測到並停止嘗試向該volume寫入數據。另一方面,刪除一個volume並不是一件小事(non-trivial),這會產生很大的影響,因爲它將使該volume上的所有block都不可訪問,並且HDFS必須處理由於刪除而導致的所有under-replicated的block。因此,Disk Checker執行最基本的檢查,使用非常保守的邏輯來確認故障。
檢查的邏輯非常的簡單,它按順序檢查DN上的以下目錄:

  • 目錄 ‘finalized’
  • 目錄 ‘tmp’
  • 目錄 ‘rbw’

檢查三個目錄時,Disk Checker將驗證:

  • 目錄及其所有的父目錄都存在,或者可以創建其他目錄。
  • 路徑確實是目錄類型。
  • 進程對目錄具有讀、寫和執行權限。

  嚴格地說,我們應該遞歸地對這3個目錄下的所有子目錄執行相同的檢查。但這會產生過多的I/O,同時幾乎沒有什麼好處——這些錯誤的block無論如何都會被添加到 Block Scanner中的可疑block中,因此它們很快就會被掃描到並報告。另一方面,類似於HBASE這類應用程序對性能非常敏感,並會努力的確保SLA,而這裏過多的I/O可能會產生無法容忍的峯值。因此,僅執行上述3項檢查。
  Block Scanner 和 Directory Scanner在DN啓動時激活並定期掃描,但Disk Checker只按需運行,Disk Checker線程是惰性創建的。具體來說,Disk Checker僅在DN在常規I/O操作(例如關閉塊或元數據文件、Directory Scanner報告錯誤等)期間捕獲到IOException時運行。另外,Disk Checker在5~6秒內最多隻能運行一次。創建Disk Checker線程時會隨機生成此特定週期。
  此外,如果啓動時出現故障的volume數大於配置的閾值,則DN將自動關閉。DN通過比較所有已配置的storage location與實際使用的storage location之間的差異來執行此初始檢查。該閾值可通過dfs.datanode.failed.volumes.allowed 配置,默認值爲0。

  Disk Checker相關的配置如下:

  • dfs.datanode.disk.check.min.gap 對DN上同一個volume的兩次連續檢查之間的最小間隔時間。支持多種時間單位後綴,如果未指定後綴,則假定爲毫秒,默認是15m。
  • dfs.datanode.disk.check.timeout 在DN啓動期間完成一個磁盤檢查所允許的最長時間。如果此時間間隔內檢查未完成,則磁盤被聲明爲Failed。支持多種時間單位後綴,如果未指定後綴,則假定爲毫秒,默認是10m。

配置整理

  上面介紹了Block Scanner, Directory Scanner, 和 Disk Checker,最後統一對這些任務相關的配置進行整理(基於Apache hadoop3.1.1版本),如下:
Block Scanner相關

  • dfs.datanode.scan.period.hours 如果爲正值,則數據節點在指定的掃描週期內不會掃描任何單個塊多次。如果爲負,則禁用Block Scanner。如果設置爲零,則使用默認值504小時或3周,默認是504。以前版本的HDFS描述的將此值設置爲0將禁用Block Scanner的說法是錯誤的。
  • dfs.block.scanner.volume.bytes.per.second 如果爲0,則將禁用DataNode的塊掃描程序。如果爲正值,則這是DataNode的Block Scanner嘗試每秒從每個volume中掃描的字節數,默認是1048576,也就是1MB。

Directory Scanner相關

  • dfs.datanode.directoryscan.interval DataNode掃描數據目錄並協調內存塊和磁盤塊之間的差異的間隔時間(秒)。支持多種時間單位,默認21600s(6小時)。
  • dfs.datanode.directoryscan.threads Directory Scanner並行執行時的線程數,默認是1。
  • dfs.datanode.directoryscan.throttle.limit.ms.per.sec 指定每秒中Directory Scanner線程運行的毫秒數。限制是針對每個線程的,不是聚合的。如爲4個compiler 線程設置100ms的限制,表示每個線程都限制爲100ms,而不是每個線程限制爲25ms。注意,限制不會中斷 report compiler thread,因此線程每秒的實際運行時間通常會比限制稍高一些,通常不會超過20%。值只有介於1和1000之間纔有效,設置無效的值將導致禁用限制並記錄錯誤消息。默認是1000毫秒,也就是禁用compiler線程限制。

Disk Checker相關

  • dfs.datanode.disk.check.min.gap 對DN上同一個volume的兩次連續檢查之間的最小間隔時間。支持多種時間單位後綴,如果未指定後綴,則假定爲毫秒,默認是15m。
  • dfs.datanode.disk.check.timeout 在DN啓動期間完成一個磁盤檢查所允許的最長時間。如果此時間間隔內檢查未完成,則磁盤被聲明爲Failed。支持多種時間單位後綴,如果未指定後綴,則假定爲毫秒,默認是10m。

參考:
https://blog.cloudera.com/hdfs-datanode-scanners-and-disk-checker-explained/
https://hadoop.apache.org/docs/r3.1.1/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml

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