hadoop 集群问题处理
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技术支持团队寻求帮助。