說說hdfs是如何處理塊副本多餘和缺失的

語言: CN / TW / HK


上一文,我們講了nn在記憶體中如何對元資料進行儲存和管理的,文章最後也提到了nn內部如何保證塊的副本數維持在指定個數,即對副本缺失的塊觸發塊副本複製,對副本多餘的塊觸發塊副本刪除。本文就來詳細聊聊具體流程及細節。


【塊副本複製的場景與處理邏輯】


哪些時候會出現需要塊的副本數不夠,需要進行塊副本複製呢?


一種是客戶端或管理員手動修改塊的副本數,將其擴大;另一種則是塊副本所在dn節點異常,包括網路異常,物理機異常,程式被kill導致的異常下線;又或者是塊副本儲存所在dn節點的磁碟異常,例如磁碟被拔掉,或者確實出現了壞盤。兩種情況都會導致塊的副本數不滿足實際設定要求。


不管哪種情況,在nn內部最終處理時(處理dn的塊彙報、處理dn的心跳超時,處理管理員或客戶端的設定),都會將不滿足副本數的塊放到UnderReplicatedBlocks中


接下來就是塊副本複製的處理流程(看圖說話)



1. 塊副本監測執行緒(ReplicationMonitorThread)定時監測是否有不滿足副本數的塊,如果有則取出塊資訊。


2. 根據塊的當前副本數情況,選擇一個作為副本複製源的dn節點,同時結合塊的儲存要求,選擇一個合適dn節點,作為複製的目的節點。


3. 然後封裝成一個任務放到複製源dn節點資訊(DatanodeDescriptor)的連結串列中。


4. 同時將塊副本複製任務進行封裝放到等待執行塊副本複製的佇列中。


5. 此後,nn在處理塊副本複製源的dn節點的心跳處理時,從佇列中取出塊副本複製任務作為心跳響應的命令下發給dn,dn節點處理心跳響應的命令,向指定的節點建立連線並傳輸塊副本資料及校驗和資料

當dn完成塊副本的資料傳輸後,目的端的dn節點會通過增量塊彙報向dn上報塊副本的資訊。


6. 在塊副本監測執行緒將塊副本複製任務放到佇列後,另外一個等待塊副本複製的監測執行緒(PendingReplicationMonitorThread)定時監測塊副本複製佇列中任務情況如果塊副本複製任務在佇列中超過指定時間,其塊的副本數仍舊沒有達到指定副本數時,將該任務從佇列取出置為超時狀態,並將其放到超時佇列中。如果已經達到指定副本數,則直接從佇列中移除。


7. 上面提到的塊副本監測執行緒在一輪處理的最後,會將超時佇列中的任務重新加到UnderReplicatedBlocks中,等待下次輪詢時再重複上面的處理邏輯


【處理中的一些細節】


首先是用於儲存塊副本數的不滿足的UnderReplicatedBlocks採用了5個佇列,每個佇列中又是一個輕量級的集合的方式進行儲存。


5個佇列實際上對應5個不同的優先順序,即對不滿足副本數的塊定義了不同的優先順序,這些塊在儲存時按按優先順序存到不同的佇列中取出時則按高優先順序到低優先順序的順序依次取出觸發塊副本複製任務。


對應原始碼:




其次,在塊副本複製的過程中,是具有一定的流控機制的。具體體現為:

  • 塊副本監測執行緒的執行是有一定時間間隔的

  • 塊副本監測執行緒每次從UnderReplicationBlocks中取出的塊個數是有限制的,每次輪詢觸發塊副本的個數為:當前線上的dn節點數 ✖️ 指定係數

  • nn通過心跳給dn下發塊副本複製任務也是有最大限制的,即如果給某個dn下發的塊副本複製任務已經達到最大數,在該dn(任意一個塊副本複製任務)未完成之前,不會再繼續下發複製任務。


這樣一來,可以確保dn節點不會瞬間因大量的副本複製任務影響到正常的讀寫流程。


【塊副本刪除的流程】


既然有不滿足副本數的場景,那麼相應的也會有超過副本數的場景,例如客戶端或管理員對某個檔案設定比原來小的副本數;或者某個dn節點異常先觸發了副本複製任務,在完成副本複製之後,異常的節點又恢復了,這個時候節點重新向nn註冊並進行塊彙報,就出現了某些塊的副本數超出了指定個數的情況。


塊副本刪除的處理邏輯和塊副本複製的處理流程幾乎相同,首先是超出副本數的塊會存放到指定的地方(InvalidBlocks);其次,同樣是在副本監測執行緒中從invalidBlocks中取出塊的資訊,並決定需要從哪個dn節點刪除對應的塊副本,構造對應的刪除任務放到dn節點資訊的某個連結串列中,然後在心跳響應中將任務下發給dn節點


最後,塊副本的刪除也同樣是具有一定流控機制的。


相關配置整理:


# 副本監測執行緒輪詢處理的時間間隔
# 預設時間間隔為3s
dfs.namenode.replication.interval

# 每次觸發副本複製的係數
# 預設為2, 即當前線上dn節點數的2倍
dfs.namenode.replication.work.multiplier.per.iteration

# 單個dn的最大副本複製任務數
# 預設值為2個
dfs.namenode.replication.max-streams

# 每次觸發副本刪除的係數
# 預設為0.32
dfs.namenode.invalidate.work.pct.per.iteration

# 單個dn副本刪除任務的上限
dfs.block.invalidate.limit


【總結】


本文主要講解了nn中塊副本複製、塊副本刪除的流程,由此可以看出,hdfs具備一套完整的機制來確保副本數與設定的數目保持一致。


裡面還可以深究的一些點,例如塊副本複製時,如何選擇源節點,目的節點的選擇會受哪些因素制約;同樣,塊副本刪除時怎麼選擇應當刪除哪個節點上的副本;塊副本的複製會產生額外的頻寬,是否會影響正常的寫等等,我們下次再聊~


好了,本文就介紹到這裡,如果覺得本文對你有些幫助,來個點贊,在看吧,也歡迎分享轉發, 謝謝~



本文分享自微信公眾號 - hncscwc(gh_383bc7486c1a)。
如有侵權,請聯絡 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。