【大數據嗶嗶集20210122】面試官問我HDFS丟不丟數據?我啪就把這個文章甩到他臉上

file

數據一致性

HDFS作爲分佈式文件系統在分佈式環境下如何保證數據一致性。HDFS中,存儲的文件將會被分成若干的大小一致的block分佈式地存儲在不同的機器上,需要NameNode節點來對這些數據進行管理,存儲這些block的結點稱爲DataNode,NameNode是用來管理這些元數據的。

NameNode保證元數據的一致性

客戶端上傳文件時,NameNode首先往edits log文件中記錄元數據的操作日誌。與此同時,NameNode將會在磁盤做一份持久化處理(fsimage文件):它跟內存中的數據是對應的,如何保證和內存中的數據的一致性?在edits logs滿之前對內存和fsimage的數據做同步,合併edits logs和fsimage上的數據,然後edits logs上的數據即可清除。而當edits logs滿之後,文件的上傳不能中斷,所以將會往一個新的文件edits.new上寫數據,而老的edits logs的合併操作將由secondNameNode來完成,即所謂的checkpoint操作。

checkpoint的觸發一般由兩種限制,一個是edits logs的大小限制,即fs.checkpoint.size配置;一個是指定時間,即fs.checkpoint.period配置。根據規定,大小的限制是優先的,規定edits文件一旦超過閾值,則不管是否達到最大時間間隔,都會強制checkpoint。

SecondaytNameNode 是 HA(High Available 高可用性)的一個解決方案,但不支持熱備,配置即可。SecondaryNameNode執行過程:從NameNode上下載元數據信息(fsimage、edits),然後把二者合併,生成新的fsimage,在本地保存,並將其推送到NameNode,替換舊的fsimage。(注:SecondaryNameNode 只存在於Hadoop1.0中,Hadoop2.0以上版本中沒有,但在僞分佈模式中是有SecondaryNameNode的,在集羣模式中是沒有SecondaryNameNode的)

SecondaryNameNode 工作流程步驟:

  • SecondaryNameNode 通知NameNode切換edits文件
  • SecondaryNameNode 從NameNode獲得fsimage和edits(通過http)
  • SecondaryNameNode 將fsimage載入內存,然後開始合併edits。同樣合併edits操作是需要滿足一定條件才進行的,有兩個條件:
    1)fs.checkpoint.period指定兩次checkpoint的最大時間間隔,默認3600秒
    2)fs.checkpoint.size規定edits文件的最大值,一旦超過這個值(默認大小是64M)則強制checkpoint,不管是否到達最大時間間隔。)
  • SecondaryNameNode 將新的fsimage發回給NameNode
  • NameNode用新的fsimage替換舊的fsimage

校驗和

HDFS 會對寫入的所有數據計算校驗和(checksum),並在讀取數據時驗證校驗和。針對指定字節的數目計算校驗和。字節數默認是512 字節,可以通過io.bytes.per.checksum屬性設置。通過CRC-32編碼後爲4字節。

DataNode 在保存數據前負責驗證checksum。client 會把數據和校驗和一起發送到一個由多個DataNode 組成的隊列中,最後一個DataNode 負責驗證checksum。如果驗證失敗,會拋出一個ChecksumException。客戶端需要處理這種異常。客戶端從DataNode 讀取數據時,也會驗證checksum。每個DataNode 都保存了一個驗證checksum的日誌。每次客戶端成功驗證一個數據塊後,都會告知DataNode ,DataNode 會更新日誌。

每個DataNode 也會在一個後臺線程中運行一個DataBlockScanner,定期驗證這個 DataNode 上的所有數據塊。在用 hadoop fs get 命令讀取文件時,可以用 -ignoreCrc 忽略驗證。如果是通過FileSystem API 讀取時,可以通過setVerifyChecksum(false),忽略驗證。Hadoop中的LocalFileSystem會進行客戶端的檢驗和,寫文件時,會在目錄下創建一個名爲.filename.crc的隱藏文件,如果想禁止校驗和功能,可以用RawLocalFileSystem代替LocalFileSystem 。

Configuration conf = ...
FileSystem fs = new RawLocalFileSystem();
fs.initialize(null, conf);

或者直接設置fs.file.impl屬性爲org.apache.hadoop.fs.RawLocalFileSystem,這樣會全局禁用checksum。LocalFileSystem內部使用了ChecksumFileSystem完成checksum工作。通過ChecksumFileSystem可以添加校驗和功能。

HA高可用

冗餘副本

HDFS處理節點失效的一個方法就是數據冗餘,即對數據做多個備份,在HDFS中可以通過配置文件設置備份的數量,如果不進行設置,這個數量默認爲3。注意參數dfs.replication.min和dfs.replication的區別:在一個塊被寫入期間,只要至少寫入了dfs.replication.min個副本數(默認是1),寫操作就會成功,直到達到其目標副本數dfs.replication(默認是3)
HDFS副本在機架上如何分佈?

HDFS採用一種稱爲機架感知的策略來改進數據的可靠性、可用性和網絡帶寬的利用率。在大多數情況下,HDFS副本系數是默認爲3(dfs.replication),HDFS的存放策略是將一個副本存放在本地機架節點上,一個副本存放在同一個機架的另一個節點上,最後一個副本放在不同機架的節點上。這種策略減少了機架間的數據傳輸,提高了寫操作的效率。機架的錯誤遠遠比節點的錯誤少,所以這種策略不會影響到數據的可靠性和可用性。與此同時,因爲數據塊只存放在兩個不同的機架上,所以此策略減少了讀取數據時需要的網絡傳輸總帶寬。

機架感知

通常,大型Hadoop集羣是以機架的形式來組織的,同一個機架上不同節點間的網絡狀況比不同機架之間的更爲理想。Namenode設法將數據塊副本保存在不同的機架上以提高容錯性
HDFS如何得知哪個Datanode在哪個機架上?

HDFS使用了一種稱爲“機架感知”的策略。HDFS不能夠自動判斷集羣中各個Datanode的網絡拓撲情況,必須通過配置dfs.network.script參數來確定節點所處的機架。文件提供了IP->rackid的翻譯,NameNode通過這個得到集羣中各個Datanode節點的rackid。

心跳機制

檢測節點失效使用“心跳機制”。每個DataNode節點週期性地向NameNode發送心跳信號。網絡分區可能導致一部分DataNode跟NameNode失去聯繫。NameNode通過心跳信號的缺失來檢測這一情況,並將這些近期不再發送心跳信號DataNode標記爲宕機,不會再將新的IO請求發給它們。

任何存儲在宕機DataNode上的數據將不再有效。DataNode的宕機可能會引起一些數據塊的副本系數低於指定值,NameNode不斷地檢測這些需要複製的數據塊,一旦發現就啓動複製操作。

在下列情況下,可能需要重新複製:
a) 某個DataNode節點失效
b) 某個副本遭到損壞
c) DataNode上的硬盤錯誤
d) 文件的冗餘因子增大

DataNode與NameNode心跳報告內容

一個數據塊在DataNode以文件存儲在磁盤上,包括兩個文件,一個是數據本身,一個是元數據包括數據塊的長度、塊數據的校驗和以及時間戳。當DataNode讀取block的時候,它會計算checksum,如果計算後的checksum,與block創建時值不一樣,說明該block已經損壞。如果塊已損壞,Client會讀取其它DataNode上的block。NameNode標記該塊已經損壞,然後複製block達到預期設置的文件備份數。

DataNode啓動後向NameNode註冊,心跳是每3秒一次,目的是告訴namenode自己的存活狀況以及可用空間。心跳返回結果帶有NameNode給該DataNode的命令如複製塊數據到另一臺機器,或刪除某個數據塊。
確認datanode宕機
(1)停止發送心跳報告
默認連續10次心跳接受不到即連續10*3=30s不間斷。這10次中間只要有1次接受到了重新記錄心跳。

(2)namenode發送檢查

在連續10次NameNode沒有接收到DataNode的心跳報告之後,NameNode斷定DataNode可能宕機了,NameNode主動向DataNode發送檢查 NameNode會開啓後臺的守護(阻塞)進程 等待檢查結果的。NameNode檢查DataNode的時間:默認5min。

默認檢查2次每次檢查5min連續2次檢查(10min)都沒有反應確認DataNode宕機了(發送一次等待5分鐘)。NameNode確認一個DataNode宕機需要的總時間: 103s+300s2=630s。

當DataNode啓動的時候,它會遍歷本地文件系統,產生一份HDFS數據塊和本地文件對應關係的列表,這就是報告塊(BlockReport),報告塊包含了DataNode上所有塊的列表。每小時DataNode默認向NameNode發送block report。彙報DataNode的數據節點情況。

安全模式

  • NameNode啓動後會進入一個稱爲安全模式的特殊狀態。處於安全模式的NameNode對於客戶端來說是隻讀的。NameNode從所有的DataNode接收心跳信號和塊狀態報告(blockreport)。

  • 每個數據塊都有一個指定的最小副本數(dfs.replication.min),當NameNode檢測確認某個數據塊的副本數目達到這個最小值,那麼該數據塊就會被認爲是副本安全(safely replicated)的。

  • 在一定百分比(這個參數配置於dfs.safemode.threshold.pct,默認值是99.9%)的數據塊被NameNode檢測確認是安全之後,再過若干時間後(這個參數配置於dfs.safemode.extension,默認值是30秒),NameNode將退出安全模式狀態。接下來NameNode會確定還有哪些數據塊的副本沒有達到指定數目,並將這些數據塊複製到其他DataNode上。

校驗和

  • HDFS會對寫入的所有數據計算校驗和(checksum),並在讀取數據時驗證。Datanode在收到客戶端的數據或者複製其他Datanode的數據時,在驗證數據後會存儲校驗和。正在寫數據的客戶端將數據及其校驗和發送到由一系列Datanode組成的管線,管線中的最後一個Datanode負責驗證校驗和。如果Datanode檢測到錯誤,客戶端便會收到一個ChecksumException
  • 客戶端從Datanode讀取數據時,也會驗證校驗和,將它們與Datanode中存儲的校驗和進行比較。每個Datanode均持久保存一個用於驗證的校驗和日誌,所以它知道每個數據塊的最後一次驗證時間。客戶端成功驗證一個數據塊後,會通知這個Datanode更新次日誌
  • 此外,每個Datanode也會在一個後臺運行一個稱爲DataBlockScanner的進程定期驗證存儲在這個Datanode上的所有數據塊。檢測到錯誤後,Namenode將這個已損壞的數據塊標記爲已損壞,之後從其他Datanode複製此數據的副本,最後使得數據的副本達到指定數目

回收站

當用戶或應用程序刪除某個文件時,這個文件並沒有立刻從HDFS中刪除。實際上,HDFS會將這個文件重命名轉移到/trash目錄。只要文件還在/trash目錄中,該文件就可以被迅速地恢復。

文件在/trash中保存的時間是可配置的(配置參數fs.trash.interval),當超過這個時間時,Namenode就會將該文件從命名空間中刪除。刪除文件會使得該文件相關的數據塊被釋放。注意,從用戶刪除文件到HDFS空閒空間的增加之間會有一定時間的延遲。

元數據保護

FsImage和Editlog是HDFS的核心數據。如果這些文件損壞了,整個HDFS都將失效。因而,Namenode可以配置成支持維護多個FsImage和Editlog的副本。任何對FsImage或者Editlog的修改,都將同步到它們的副本上。這種多副本的同步操作可能會降低Namenode每秒處理的名字空間事務數量。然而這個代價是可以接受的,因爲即使HDFS的應用是數據密集的,它們也非元數據密集的。當Namenode重啓的時候,它會選取最近的完整的FsImage和Editlog來使用

快照機制

快照支持某一特定時刻的數據的複製備份。利用快照,可以讓HDFS在數據損壞時恢復到過去一個已知正確的時間點。HDFS目前還不支持快照功能,但計劃會在將來的版本支持。

容錯機制

故障的類型主要有以下三種,針對這三種故障類型,HDFS提供了不同的故障檢測機制:

針對DataNode失效問題,HDFS使用了心跳機制,DataNode定期向NameNode發送心跳信息,NameNode根據心跳信息判斷DataNode是否存活
針對網絡故障而導致無法收發數據的問題,HDFS提供了ACK的機制,在發送端發送數據後,如果沒有收到ACK並且經過多次重試後仍然如此,則認爲網絡故障
針對數據損壞問題,所有DataNode會定期向NameNode發送自身存儲的塊清單,在傳輸數據的同時會發送總和校驗碼,NameNode依次來判斷數據是否丟失或損壞

讀容錯

讀失敗時:

  • DFSInputStream 會去嘗試連接列表裏的下一個 DataNode ,同時記錄下這個異常節點
  • DFSInputStream 也會對獲取到的數據覈查 checknums 。如果損壞的 block 被發現了,DFSInputStream 就試圖從另一個擁有備份的 DataNode 中去讀取備份塊中的數據
  • 最後異常數據的同步工作也是由 NameNode 來安排完成

寫容錯

當寫流程中一臺 DataNode 宕機了:

首先 pipeline 被關閉,在確認隊列中的剩下的 package 會被添加進數據隊列的起始位置上不再發送,以防止在失敗的節點下游的節點再丟失數據
然後,存儲在正常的 DataNode 上的 block 會被指定一個新的標識,並將該標識傳遞給 NameNode,以便故障DataNode在恢復後可以刪除自己存儲的那部分已經失效的數據塊
失敗節點會從 pipeline 中移除,然後剩下兩個好的 DataNode 會組成一個的新的 pipeline ,剩下的這些 block 的包會繼續寫進 pipeline 中正常的 DataNode 中
最後,NameNode 會發現節點宕機導致部分 block 的塊備份數小於規定的備份數,此時NameNode 會安排使節點的備份數滿足 dfs.replication 配置要求

DataNode失效

在NameNode中會持有數據塊表和DataNode兩張表。數據塊表存儲着某個數據塊(包括副本)所在的DataNode,DataNode表存儲着每個DataNode中保存的數據塊列表。由於DataNode會週期性地給NameNode發送自己所持有的數據塊信息,因此NameNode會持續更新數據塊表和DataNode表。如果發現某個DataNode上的數據塊錯誤,NameNode會從數據塊表刪除該數據塊;如果發現某個DataNode失效,NameNode會對兩張表進行更新。NameNode還會週期性地掃描數據塊表,如果發現數據塊表中某個數據庫的備份數量低於所設置的備份數,則會協調從其它DataNode複製數據到另一個DataNode上完成備份。

HDFS副本放置策略

如果寫請求出現在某個DataNode上,第一個副本就會存放在當前DataNode所在的機器上,如果該機器負載過重,可以將該備份放在同一個機架上的隨機機器上。接着第二個副本就會存放在不同於第一個副本所在機架的機架上,第三個副本會隨機存放在第二個副本所在機架的任一DataNode上。

在三個副本的情況下,第一個副本與原數據在相同機器上,另外兩個副本放在其它機架的隨機機器上。這樣的設置可以使得性能與容災兼備,優先從同機器上獲取備份數據,減少數據傳輸開銷;在該機器宕機的情況下,從另一個機架獲取備份數據,避免同一個機架的機器集體宕機的情況出現。

HDFS的HA架構

以上的所有容錯都是基於DataNode的故障問題進行考慮的,但是NameNode本身就存在單點故障,如果NameNode出現故障,則整個集羣會直接宕機。因此HDFS提供了HA的架構,對於一個典型的HA集羣而言,NameNode會被配置在兩臺獨立的機器上,在任何時間上,一個NameNode處於Active狀態,而另一個NameNode處於Standby狀態,Active狀態的NameNode會響應集羣中所有的客戶端的請求,Standby狀態的NameNode只是作爲一個副本,保證在必要的時候提供一個快速的轉移,使得上層對NameNode的切換無感知,Standby NameNode與Active NameNode應時刻保持同步,在Active NameNode和Standby NameNode之間要有個共享的存儲日誌的地方,Active NameNode把EditLog寫到共享的存儲日誌中,Standby NameNode讀取日誌並執行,使得Active NameNode和Standby NameNode內存中的HDFS元數據保持同步。

file

歡迎關注,《大數據成神之路》系列文章

歡迎關注,《大數據成神之路》系列文章

歡迎關注,《大數據成神之路》系列文章

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