?
1.1.JournalNode 的作用
在 HDFS HA 配置中,為了實現兩個 NameNode 之間的狀態同步和故障自動切換,Hadoop 使用了一組 JournalNode 來管理共享的編輯日志。具體來說,JournalNode 的主要職責包括:
- 共享編輯日志:JournalNode 節點組成了一個分布式系統,用于存儲 HDFS 的編輯日志(Edit Logs)。這兩個日志文件記錄了對 HDFS 所做的所有更改,如文件創建、刪除等操作。
- 支持 NameNode 故障轉移:通過共享編輯日志,使得 Standby NameNode 可以實時讀取 Active NameNode 上的所有變更,并在必要時快速接管成為新的 Active NameNode,從而保證 HDFS 的高可用性。
1.2存儲的數據
JournalNode 主要存儲的是 HDFS 編輯日志(Edit Logs),這些日志包含了對文件系統所做的所有修改。具體來說,JournalNode 存儲的內容包括:
- Edit Logs:這是最核心的數據,包含了對 HDFS 文件系統的每一個寫操作(例如創建文件、重命名文件、刪除文件等)的日志條目。Active NameNode 將這些日志條目標記為已完成之后,會將它們發送到 JournalNodes 進行持久化存儲。
- Checkpoint 數據:雖然 Checkpoint 主要是由 Secondary NameNode 或者 Standby NameNode 完成的,但是在這個過程中也會涉及到與 JournalNode 的交互。Checkpoint 是一種優化措施,它通過合并 edits 和 fsimage 文件來減少 edits 文件的數量和大小,以便加速 NameNode 的啟動時間。
JournalNode 的作用:
- JournalNode 是 HA 集群的核心組件,負責存儲和同步 NameNode 的編輯日志。
- 格式化后,JournalNode 的?
VERSION
?文件會自動更新為與主 NameNode 一致的?namespaceID
。
2.1NameNode 中存儲的內容
NameNode 在 HDFS 中扮演著至關重要的角色,它負責管理文件系統的命名空間,并控制客戶端對文件的訪問。具體來說,NameNode 存儲以下兩類信息:
- 命名空間鏡像(Namespace Image):這是整個文件系統的快照,包括所有目錄和文件的層次結構、權限、修改時間等元數據信息。
- 編輯日志(Edit Log):記錄了對HDFS執行的所有更改操作,如創建文件、刪除文件等。這些日志允許 NameNode 恢復其狀態到最近的一個點。
此外,NameNode 還維護著每個 DataNode 上的數據塊映射信息,即哪些數據塊存儲在哪些 DataNode 上。不過,這部分信息不是持久存儲的,而是在 NameNode 啟動時通過 DataNode 的心跳消息動態重建的。
查看journalnode 的節點版本
[hadoop@hadoop-001 current]$ cat VERSION
#Wed Jul 16 00:41:58 CST 2025
namespaceID=1793617653
clusterID=CID-96504837-e7a7-4398-9674-0cec0011450e
cTime=1752597718569
storageType=JOURNAL_NODE
layoutVersion=-66[hadoop@hadoop-001 mycluster]$ ll
total 4
drwx------ 3 hadoop hadoop 4096 Jul 16 01:12 current
drwxrwxr-x 2 hadoop hadoop 6 Jul 16 00:43 edits.sync-rw-rw-r-- 1 hadoop hadoop 8 Jul 16 01:12 committed-txid
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 00:47 edits_0000000000000000001-0000000000000000002
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 00:50 edits_0000000000000000003-0000000000000000004
-rw-rw-r-- 1 hadoop hadoop 116 Jul 16 00:52 edits_0000000000000000005-0000000000000000007
-rw-rw-r-- 1 hadoop hadoop 296 Jul 16 00:54 edits_0000000000000000008-0000000000000000012
-rw-rw-r-- 1 hadoop hadoop 69 Jul 16 00:56 edits_0000000000000000013-0000000000000000015
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 00:58 edits_0000000000000000016-0000000000000000017
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:00 edits_0000000000000000018-0000000000000000019
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:02 edits_0000000000000000020-0000000000000000021
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:04 edits_0000000000000000022-0000000000000000023
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:06 edits_0000000000000000024-0000000000000000025
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:08 edits_0000000000000000026-0000000000000000027
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:10 edits_0000000000000000028-0000000000000000029
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:12 edits_0000000000000000030-0000000000000000031
-rw-rw-r-- 1 hadoop hadoop 1048576 Jul 16 01:12 edits_inprogress_0000000000000000032
-rw-rw-r-- 1 hadoop hadoop 2 Jul 16 00:44 last-promised-epoch
-rw-rw-r-- 1 hadoop hadoop 2 Jul 16 00:44 last-writer-epoch
drwxrwxr-x 2 hadoop hadoop 6 Jul 16 00:41 paxos
-rw-rw-r-- 1 hadoop hadoop 167 Jul 16 00:41 VERSION[hadoop@hadoop-001 current]$ cat VERSION
#Wed Jul 16 00:41:58 CST 2025
namespaceID=1793617653
clusterID=CID-96504837-e7a7-4398-9674-0cec0011450e
cTime=1752597718569
storageType=NAME_NODE
blockpoolID=BP-1986497784-192.168.64.141-1752597718569
layoutVersion=-66total 1092
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 00:47 edits_0000000000000000001-0000000000000000002
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 00:50 edits_0000000000000000003-0000000000000000004
-rw-rw-r-- 1 hadoop hadoop 116 Jul 16 00:52 edits_0000000000000000005-0000000000000000007
-rw-rw-r-- 1 hadoop hadoop 296 Jul 16 00:54 edits_0000000000000000008-0000000000000000012
-rw-rw-r-- 1 hadoop hadoop 69 Jul 16 00:56 edits_0000000000000000013-0000000000000000015
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 00:58 edits_0000000000000000016-0000000000000000017
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:00 edits_0000000000000000018-0000000000000000019
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:02 edits_0000000000000000020-0000000000000000021
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:04 edits_0000000000000000022-0000000000000000023
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:06 edits_0000000000000000024-0000000000000000025
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:08 edits_0000000000000000026-0000000000000000027
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:10 edits_0000000000000000028-0000000000000000029
-rw-rw-r-- 1 hadoop hadoop 42 Jul 16 01:12 edits_0000000000000000030-0000000000000000031
-rw-rw-r-- 1 hadoop hadoop 1048576 Jul 16 01:12 edits_inprogress_0000000000000000032
-rw-rw-r-- 1 hadoop hadoop 401 Jul 16 00:41 fsimage_0000000000000000000
-rw-rw-r-- 1 hadoop hadoop 62 Jul 16 00:41 fsimage_0000000000000000000.md5
-rw-rw-r-- 1 hadoop hadoop 3 Jul 16 01:12 seen_txid
-rw-rw-r-- 1 hadoop hadoop 219 Jul 16 00:41 VERSION[hadoop@hadoop-001 current]$ cat seen_txid
32[hadoop@hadoop-001 current]$ ll
total 4
drwx------ 4 hadoop hadoop 54 Jul 16 00:44 BP-1986497784-192.168.64.141-1752597718569
-rw-rw-r-- 1 hadoop hadoop 229 Jul 16 00:44 VERSION[hadoop@hadoop-001 current]$ cat VERSION
#Wed Jul 16 00:44:06 CST 2025
storageID=DS-2ee79306-97af-4874-b006-1780dcdcdd55
clusterID=CID-96504837-e7a7-4398-9674-0cec0011450e
cTime=0
datanodeUuid=1173be70-504f-4c07-8fab-187c04e866f3
storageType=DATA_NODE
layoutVersion=-57
?
為什么要格式化 ZKFC?
初始化 ZKFC 的狀態
- 初次部署 HA 集群時:當首次配置 Hadoop HA 集群時,ZKFC 需要與 Zookeeper 集群建立連接,并創建必要的臨時節點(ZNode)以管理 NameNode 的 Active/Standby 狀態。格式化 ZKFC 會清空 Zookeeper 中舊的配置信息,確保從空白狀態開始初始化。
- 清除舊的配置殘留:如果之前嘗試過配置 HA 但失敗或部分完成,Zookeeper 中可能殘留無效的 ZNode。格式化 ZKFC 會刪除這些殘留數據,避免干擾新配置。
同步配置變更
- 修改 NameNode 的 RPC 端口:如果 NameNode 的 RPC 端口被修改(例如從默認的?
8020
?改為其他端口),ZKFC 需要更新 Zookeeper 中存儲的節點信息。此時必須重新格式化 ZKFC,否則 ZKFC 會基于舊的端口信息嘗試連接 NameNode,導致連接失敗。 - 其他配置變更:如修改 NameNode 的主機名、Zookeeper 集群地址等,也需要通過格式化 ZKFC 來同步新配置到 Zookeeper。
- 修改 NameNode 的 RPC 端口:如果 NameNode 的 RPC 端口被修改(例如從默認的?
解決 HA 選舉失敗問題
- ZKFC 狀態不一致:如果兩個 NameNode 的 ZKFC 實例因配置錯誤或網絡問題未能正確選舉出 Active 狀態的 NameNode(例如兩者都處于 Standby 狀態),格式化 ZKFC 可以強制重置 Zookeeper 中的鎖節點(ZNode),重新觸發選舉流程。
- 避免腦裂(Split-Brain):格式化 ZKFC 可以確保只有一個 ZKFC 實例在 Zookeeper 中持有鎖節點,防止多個 NameNode 同時被誤判為 Active 狀態,導致數據不一致。
修復 ZKFC 與 Zookeeper 的通信問題
- Zookeeper 節點損壞:如果 Zookeeper 中的 ZKFC 相關節點(如?
zkLockFilePath
)因異常退出或配置錯誤而損壞,格式化 ZKFC 會重建這些節點,恢復正常的通信和選舉機制。 - ZKFC 會話失效:當 ZKFC 的 Zookeeper 會話因網絡中斷或超時而失效時,格式化 ZKFC 可以重新建立會話,確保 ZKFC 能夠繼續監控 NameNode 狀態。
- Zookeeper 節點損壞:如果 Zookeeper 中的 ZKFC 相關節點(如?
格式化 ZKFC 的典型場景
場景 | 原因 | 操作 |
---|---|---|
初次部署 HA 集群 | 初始化 ZKFC 和 Zookeeper 的狀態 | 執行?hdfs zkfc -formatZK |
修改 NameNode 的 RPC 端口 | 更新 Zookeeper 中的節點信息 | 格式化 ZKFC 并重啟 HDFS |
HA 集群異常(所有 NameNode 處于 Standby) | 清除舊的鎖節點并重新選舉 | 格式化 ZKFC 并重啟 HDFS |
ZKFC 與 Zookeeper 通信失敗 | 修復損壞的 ZNode 或會話 | 格式化 ZKFC 并重啟服務 |
格式化 ZKFC 的注意事項
備份重要數據:
- 格式化 ZKFC 會刪除 Zookeeper 中與 HA 相關的節點(如?
zkLockFilePath
?和?zkBreadCrumbPath
),可能導致當前 Active/Standby 狀態丟失。執行前需確認是否需要保留現有狀態。 - 如果集群中有正在進行的故障轉移或元數據同步,建議先停止 HDFS 服務再執行格式化。
- 格式化 ZKFC 會刪除 Zookeeper 中與 HA 相關的節點(如?
僅在主 NameNode 上操作:
- 格式化 ZKFC 通常只需要在?主 NameNode?上執行一次。備用 NameNode 的 ZKFC 會自動從 Zookeeper 同步狀態。
- 如果兩個 NameNode 的 RPC 端口都被修改,只需在其中一個節點執行格式化即可。
驗證格式化結果:
- 格式化后,檢查 Zookeeper 中的 ZNode 是否已更新(例如使用?
zkCli.sh
?連接 Zookeeper 并查看節點路徑)。 - 啟動 HDFS 后,通過?
hdfs haadmin -getServiceState nn1
?和?hdfs haadmin -getServiceState nn2
?驗證 NameNode 狀態是否正常。
- 格式化后,檢查 Zookeeper 中的 ZNode 是否已更新(例如使用?
?
格式化 NameNode 是 Hadoop 集群配置中的一個重要步驟,它主要用于初始化 HDFS 的文件系統元數據存儲。理解 NameNode 中存儲的內容以及為什么需要進行格式化,有助于更好地管理 Hadoop 集群。
?
為什么要格式化 NameNode
格式化 NameNode 主要是為了初始化一個新的 HDFS 文件系統實例。當你首次設置一個 Hadoop 集群或添加了一個新的 NameNode 時,你需要對其進行格式化。這個過程會創建一個新的命名空間鏡像,并清空編輯日志。以下是需要格式化 NameNode 的幾種常見場景:
- 新建集群:如果你正在構建一個新的 Hadoop 集群,那么需要格式化 NameNode 來創建一個新的 HDFS 實例。
- 恢復出廠設置:如果你想清除現有集群上的所有數據并從頭開始,格式化 NameNode 可以達到這一目的。但請注意,這是一個破壞性操作,因為它會刪除所有已存儲的數據。
- 修復嚴重問題:在某些極端情況下,如果文件系統元數據嚴重損壞且無法修復,可能需要通過格式化 NameNode 來解決問題。然而,這通常只作為最后的手段,因為這意味著丟失所有數據。
hdfs namenode format 為什么不需要在兩個節點都執行格式化?
NameNode 元數據同步機制:
- 在 HA 模式下,NameNode 的元數據(如?
fsimage
?和?edits
?日志)通過?JournalNode?共享。 - 格式化操作會在主 NameNode 上生成新的?
namespaceID
?和?clusterID
,并通過 JournalNode 同步到備用 NameNode。 - 如果在兩個 NameNode 上分別執行格式化,會導致?
namespaceID
?不一致,進而引發以下問題:Incompatible namespaceID
?錯誤。- JournalNode 無法識別日志文件。
- HA 無法正常工作。
- 在 HA 模式下,NameNode 的元數據(如?
?
停止所有服務:
stop-dfs.sh zkServer.sh stop # 如果啟用了 ZooKeeper
備份數據(可選但推薦):
- 備份 NameNode 和 JournalNode 的存儲目錄:
cp -r /path/to/dfs/name /path/to/backup/ cp -r /path/to/journal/data /path/to/backup/
- 備份 NameNode 和 JournalNode 的存儲目錄:
格式化主 NameNode:
- 在主 NameNode 節點(例如?
nn1
)上執行:hdfs namenode -format
- 確保輸出中包含?
Formatting using clusterID: CID-xxxx
。
- 在主 NameNode 節點(例如?
遇到問題
92.168.64.142:8485: Incompatible namespaceID for journal Storage Directory root= /var/lib/hadoop/journal/mycluster; location= null: NameNode has nsId 487907681 but storage has nsId 1670315560at org.apache.hadoop.hdfs.qjournal.server.JNStorage.checkConsistentNamespace(JNStorage.java:275)at org.apache.hadoop.hdfs.qjournal.server.Journal.newEpoch(Journal.java:343)at org.apache.hadoop.hdfs.qjournal.server.JournalNodeRpcServer.newEpoch(JournalNodeRpcServer.java:174)at org.apache.hadoop.hdfs.qjournal.protocolPB.QJournalProtocolServerSideTranslatorPB.newEpoch(QJournalProtocolServerSideTranslatorPB.java:137)at org.apache.hadoop.hdfs.qjournal.protocol.QJournalProtocolProtos$QJournalProtocolService$2.callBlockingMethod(QJournalProtocolProtos.java:31920)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:604)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:572)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:556)at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:1093)at org.apache.hadoop.ipc.Server$RpcCall.run(Server.java:1043)at org.apache.hadoop.ipc.Server$RpcCall.run(Server.java:971)at java.security.AccessController.doPrivileged(Native Method)at javax.security.auth.Subject.doAs(Subject.java:422)at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1878)at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2976)at org.apache.hadoop.hdfs.qjournal.client.QuorumException.create(QuorumException.java:81)at org.apache.hadoop.hdfs.qjournal.client.QuorumCall.rethrowException(QuorumCall.java:305)at org.apache.hadoop.hdfs.qjournal.client.AsyncLoggerSet.waitForWriteQuorum(AsyncLoggerSet.java:143)at org.apache.hadoop.hdfs.qjournal.client.QuorumJournalManager.createNewUniqueEpoch(QuorumJournalManager.java:244)at org.apache.hadoop.hdfs.qjournal.client.QuorumJournalManager.recoverUnfinalizedSegments(QuorumJournalManager.java:478)at org.apache.hadoop.hdfs.server.namenode.JournalSet$6.apply(JournalSet.java:637)at org.apache.hadoop.hdfs.server.namenode.JournalSet.mapJournalsAndReportErrors(JournalSet.java:392)at org.apache.hadoop.hdfs.server.namenode.JournalSet.recoverUnfinalizedSegments(JournalSet.java:634)at org.apache.hadoop.hdfs.server.namenode.FSEditLog.recoverUnclosedStreams(FSEditLog.java:1655)at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.startActiveServices(FSNamesystem.java:1327)at org.apache.hadoop.hdfs.server.namenode.NameNode$NameNodeHAContext.startActiveServices(NameNode.java:2029)at org.apache.hadoop.hdfs.server.namenode.ha.ActiveState.enterState(ActiveState.java:61)at org.apache.hadoop.hdfs.server.namenode.ha.HAState.setStateInternal(HAState.java:64)at org.apache.hadoop.hdfs.server.namenode.ha.StandbyState.setState(StandbyState.java:60)at org.apache.hadoop.hdfs.server.namenode.NameNode.transitionToActive(NameNode.java:1882)at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.transitionToActive(NameNodeRpcServer.java:1816)at org.apache.hadoop.ha.protocolPB.HAServiceProtocolServerSideTranslatorPB.transitionToActive(HAServiceProtocolServerSideTranslatorPB.java:112)at org.apache.hadoop.ha.proto.HAServiceProtocolProtos$HAServiceProtocolService$2.callBlockingMethod(HAServiceProtocolProtos.java:6218)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:604)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:572)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEng
個人這種是重新格式化了namenode ,journalnode 中的數據是舊數據
2025-07-16 00:29:23,377 INFO retry.RetryInvocationHandler: java.net.ConnectException: Call From hadoop-001/192.168.64.141 to hadoop-002:8020 failed on connection exception: java.net.ConnectException: Connection refused; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused, while invoking ClientNamenodeProtocolTranslatorPB.getFileInfo over hadoop-002/192.168.64.142:8020 after 1 failover attempts. Trying to failover after sleeping for 709ms.
2025-07-16 00:29:24,098 INFO retry.RetryInvocationHandler: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.StandbyException): Operation category READ is not supported in state standby. Visit https://s.apache.org/sbnn-errorat org.apache.hadoop.hdfs.server.namenode.ha.StandbyState.checkOperation(StandbyState.java:108)at org.apache.hadoop.hdfs.server.namenode.NameNode$NameNodeHAContext.checkOperation(NameNode.java:2094)at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.checkOperation(FSNamesystem.java:1550)at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getFileInfo(FSNamesystem.java:3342)at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.getFileInfo(NameNodeRpcServer.java:1208)at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.getFileInfo(ClientNamenodeProtocolServerSideTranslatorPB.java:1042)at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:604)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:572)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:556)at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:1093)at org.apache.hadoop.ipc.Server$RpcCall.run(Server.java:1043)at org.apache.hadoop.ipc.Server$RpcCall.run(Server.java:971)at java.security.AccessController.doPrivileged(Native Method)at javax.security.auth.Subject.doAs(Subject.java:422)at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1878)at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2976)
, while invoking ClientNamenodeProtocolTranslatorPB.getFileInfo over hadoop-001/192.168.64.141:8020 after 2 failover attempts. Trying to failover after sleeping for 1744ms.
2025-07-16 00:29:25,846 INFO retry.RetryInvocationHandler: java.net.ConnectException: Call From hadoop-001/192.168.64.141 to hadoop-002:8020 failed on connection exception: java.net.ConnectException: Connection refused; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused, while invoking ClientNamenodeProtocolTranslatorPB.getFileInfo over hadoop-002/192.168.64.142:8020 after 3 failover attempts. Trying to failover after sleeping for 4704ms.
啟動一個namenode ,另一個namenode 給掛了,或者說namenode? 一個沒有啟動,這個一個是journalnode 問題,一個是兩個namenode 數據不一致導致的
192.168.64.143:8485: Call From hadoop-002/192.168.64.142 to hadoop-003:8485 failed on connection exception: java.net.ConnectException: Connection refused; For more details see: http://wiki.apache.org/hadoop/ConnectionRefusedat org.apache.hadoop.hdfs.qjournal.client.QuorumException.create(QuorumException.java:81)at org.apache.hadoop.hdfs.qjournal.client.QuorumCall.rethrowException(QuorumCall.java:305)at org.apache.hadoop.hdfs.qjournal.client.AsyncLoggerSet.waitForWriteQuorum(AsyncLoggerSet.java:143)at org.apache.hadoop.hdfs.qjournal.client.QuorumJournalManager.createNewUniqueEpoch(QuorumJournalManager.java:233)at org.apache.hadoop.hdfs.qjournal.client.QuorumJournalManager.recoverUnfinalizedSegments(QuorumJournalManager.java:478)at org.apache.hadoop.hdfs.server.namenode.JournalSet$6.apply(JournalSet.java:637)at org.apache.hadoop.hdfs.server.namenode.JournalSet.mapJournalsAndReportErrors(JournalSet.java:392)at org.apache.hadoop.hdfs.server.namenode.JournalSet.recoverUnfinalizedSegments(JournalSet.java:634)at org.apache.hadoop.hdfs.server.namenode.FSEditLog.recoverUnclosedStreams(FSEditLog.java:1655)at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.startActiveServices(FSNamesystem.java:1327)at org.apache.hadoop.hdfs.server.namenode.NameNode$NameNodeHAContext.startActiveServices(NameNode.java:2029)at org.apache.hadoop.hdfs.server.namenode.ha.ActiveState.enterState(ActiveState.java:61)at org.apache.hadoop.hdfs.server.namenode.ha.HAState.setStateInternal(HAState.java:64)at org.apache.hadoop.hdfs.server.namenode.ha.StandbyState.setState(StandbyState.java:60)at org.apache.hadoop.hdfs.server.namenode.NameNode.transitionToActive(NameNode.java:1882)at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.transitionToActive(NameNodeRpcServer.java:1816)at org.apache.hadoop.ha.protocolPB.HAServiceProtocolServerSideTranslatorPB.transitionToActive(HAServiceProtocolServerSideTranslatorPB.java:112)at org.apache.hadoop.ha.proto.HAServiceProtocolProtos$HAServiceProtocolService$2.callBlockingMethod(HAServiceProtocolProtos.java:6218)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:604)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:572)at org.apache.hadoop.ipc.ProtobufRpcEngine2$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine2.java:556)at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:1093)at org.apache.hadoop.ipc.Server$RpcCall.run(Server.java:1043) hadoop namenode
jouarnalnode 沒有啟動導致namenode 無法啟動, 這個清理journalnode 目錄重啟journalnode?
1. 命名空間 ID 不一致的含義
namespaceID
?是 HDFS 集群的唯一標識符,由 NameNode 在首次格式化時生成,并寫入?fsimage
?和?edits
?文件的?VERSION
?元數據中。- JournalNode 的作用:
- 在 HA 模式下,JournalNode 負責存儲 NameNode 的編輯日志(Edit Log),兩個 NameNode 通過共享 JournalNode 的日志實現元數據同步。
- JournalNode 的?
VERSION
?文件必須與 Active/Standby NameNode 的?VERSION
?文件中的?namespaceID
?一致,否則無法識別日志。
2. 根因排查
- 格式化 NameNode 或 ZKFC 后未同步 JournalNode:
- 如果 NameNode 被重新格式化(如?
hdfs namenode -format
),會生成新的?namespaceID
,但 JournalNode 的?VERSION
?文件未更新,導致不一致。
- 如果 NameNode 被重新格式化(如?
- JournalNode 存儲目錄殘留舊數據:
- JournalNode 的?
dfs.journalnode.edits.dir
?目錄(如?/var/lib/hadoop/journal/mycluster
)中可能殘留了舊的?namespaceID
。
- JournalNode 的?
- JournalNode 未正確初始化:
- JournalNode 啟動時未從 NameNode 獲取最新的?
namespaceID
,導致元數據不一致。
- JournalNode 啟動時未從 NameNode 獲取最新的?
解決步驟
1. 停止所有服務
- 停止 HDFS 服務:
stop-dfs.sh
- 停止 ZooKeeper 服務(如果啟用 HA):
zkServer.sh stop
2. 備份 JournalNode 數據
- 備份 JournalNode 存儲目錄:
cp -r /var/lib/hadoop/journal/mycluster /var/lib/hadoop/journal/mycluster.bak
3. 修改 JournalNode 的?namespaceID
找到 NameNode 的
namespaceID
:- 查看 NameNode 的?
VERSION
?文件(路徑為?dfs.name.dir/current/VERSION
):cat /opt/hadoop/dfs/name/current/VERSION
- 示例輸出:
namespaceID=487907681
- 查看 NameNode 的?
修改 JournalNode 的
VERSION
文件:- 編輯 JournalNode 存儲目錄下的?
VERSION
?文件(路徑為?dfs.journalnode.edits.dir/ns<nameservice_id>/current/VERSION
):vi /var/lib/hadoop/journal/mycluster/current/VERSION
- 將?
namespaceID
?修改為與 NameNode 一致的值(如?487907681
):namespaceID=487907681
- 編輯 JournalNode 存儲目錄下的?
4. 清理 JournalNode 日志(可選)
- 如果 JournalNode 存儲目錄中有舊的編輯日志(如?
edits_*.xxx
),可以刪除以避免事務 ID 間隙:rm -rf /var/lib/hadoop/journal/mycluster/ns<nameservice_id>/*
5. 啟動服務并驗證
啟動 JournalNode:
hdfs journalnode
啟動 NameNode 和 ZKFC:
hdfs namenode hdfs zkfc
驗證 HA 狀態:
- 檢查 NameNode 狀態:
hdfs haadmin -getServiceState nn1 hdfs haadmin -getServiceState nn2
- 檢查 JournalNode 日志是否正常:
tail -f /var/log/hadoop/hadoop-hdfs-journalnode-<hostname>.log
- 檢查 NameNode 狀態:
常見錯誤排查
錯誤場景 | 檢查點 | 解決方法 |
---|---|---|
JournalNode 與 NameNode?namespaceID ?不一致 | VERSION ?文件中?namespaceID ?不匹配 | 手動修改 JournalNode 的?VERSION ?文件 |
JournalNode 存儲目錄權限問題 | Hadoop 用戶無權限訪問?/var/lib/hadoop/journal | 修改目錄權限:chown -R hdfs:hdfs /var/lib/hadoop/journal |
JournalNode 未同步最新的編輯日志 | 日志中存在事務 ID 間隙 | 清理舊日志并重啟 JournalNode |
ZooKeeper 元數據殘留 | /hadoop-ha ?節點殘留舊數據 | 手動刪除節點或重新格式化 ZKFC |
根據您的描述,在Hadoop高可用(HA)集群中,將一臺NameNode的數據復制到另一臺后導致兩個NameNode都處于Standby狀態,這是一個常見的故障場景。這通常是由于元數據不一致或ZooKeeper協調失敗引起的。以下是基于最佳實踐的解決步驟,請按順序操作:
### 解決步驟
1. **停止集群服務** ?
確保所有Hadoop進程安全停止,避免數據沖突:
```bash
stop-dfs.sh
stop-yarn.sh ?# 如果YARN也在運行
```
2. **檢查并清理ZooKeeper狀態** ?
NameNode狀態由ZooKeeper管理,需重新初始化:
- 啟動ZooKeeper服務(確保所有ZooKeeper節點正常運行):
```bash
zkServer.sh start
```
- 在任意NameNode節點上執行ZooKeeper格式化命令,重置HA狀態:
```bash
hdfs zkfc -formatZK
```
3. **同步元數據并格式化NameNode** ?
- 刪除所有DataNode和NameNode的本地數據目錄(確保數據可丟失或已備份):
```bash
rm -rf /path/to/dfs/name ?# NameNode元數據目錄
rm -rf /path/to/dfs/data ?# DataNode數據目錄
```
> 注意:路徑需根據`hdfs-site.xml`中的`dfs.name.dir`和`dfs.data.dir`配置修改。
- 格式化主NameNode:
```bash
hdfs namenode -format
```
4. **啟動集群并驗證狀態** ?
- 啟動Hadoop服務:
```bash
start-dfs.sh
start-yarn.sh ?# 如需啟動YARN
```
- 檢查NameNode狀態:
```bash
hdfs haadmin -getServiceState nn1 ?# 替換nn1為實際NameNode ID
hdfs haadmin -getServiceState nn2
```
- 一個節點應顯示為`active`,另一個為`standby`。
- 訪問HDFS Web UI(默認端口50070或9870)確認狀態正常。
### 關鍵注意事項
- **數據丟失風險**:上述操作會刪除現有數據,僅適用于測試環境或數據可重建的場景。生產環境請先備份元數據。
- **權限和配置**:確保所有節點的配置文件(`core-site.xml`、`hdfs-site.xml`)一致,特別是`dfs.nameservices`、`dfs.ha.namenodes.*`等HA相關參數。
- **常見問題**:
- 如果ZKFC進程無法啟動,檢查ZooKeeper連接配置。
- 如果NameNode進入安全模式,運行`hdfs dfsadmin -safemode leave`強制退出。
如果問題持續,建議查看NameNode日志(位于`$HADOOP_HOME/logs`目錄)以獲取具體錯誤信息。
系統斷電后NameNode無法啟動,可能是由數據塊丟失、EditLog損壞或節點ID不一致等原因導致的,以下是具體分析和解決方法:
- 數據塊丟失導致進入安全模式:斷電可能使客戶端寫入的數據未及時保存到磁盤,導致數據塊丟失。當丟失比例達到一定程度,NameNode啟動時會因不滿足最小副本條件而一直處于安全模式,無法正常啟動。可先啟動HDFS所有服務,使用?fsck?命令查看是否有損壞的塊,然后在NameNode節點上使用?dfsadmin?命令離開安全模式,再用?fsck?命令將丟失的塊刪除,最后重啟HDFS相關服務。
- EditLog損壞:JournalNode上的EditLog可能因斷電而損壞或不連續,導致NameNode啟動失敗。可查看配置項“dfs.namenode.name.dir”獲取NameNode數據目錄,找到最新的FSImage文件序號,再查看配置項“dfs.journalnode.edits.dir”獲取JournalNode的數據目錄,檢查從該序號開始的edits文件是否連續。若不連續,從其他JournalNode或NameNode數據目錄中找到連續的片段復制過來,修復后重啟NameNode。
- 節點ID不一致:如果多次格式化NameNode,可能會導致NameNode和DataNode的clusterID不一樣,從而使NameNode啟動失敗。可查看“/home/zkpk/hadoopdata/dfs/name/current/VERSION”文件中的namespaceID,修改每個Slave的clusterID使其與Master的clusterID一致,或者修改Master的clusterID使其與Slave的clusterID一致。
若上述方法都無法解決問題,可查看NameNode的日志文件,根據具體報錯信息進一步排查,或聯系Hadoop技術支持團隊尋求幫助。
?
?
?