转自:http://www.xuebuyuan.com/2129593.html
解决办法:
1.关闭hadoop 和 spark;
2.格式化namenode
hadoop namenode -format
各个datanode的storageID不一样,导致启动datanode不成功。
我们在启动hadoop各个节点时,启动namenode和datanode,这个时候如果datanode的storageID不一样,那么会导致如下datanode注册不成功的信息:
14/04/24 15:11:10 INFO ipc.Server: IPC Server handler 7 on 8022, call org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol.blockReport from 192.168.1.201:35827: error: org.apache.hadoop.hdfs.protocol.UnregisteredNodeException: Data node DatanodeRegistration(192.168.1.201,
storageID=DS-1931411854-192.168.137.102-50010-1394165319679, infoPort=50075, ipcPort=50020, storageInfo=lv=-40;cid=cluster45;nsid=300226841;c=0) is attempting to report storage ID DS-1931411854-192.168.137.102-50010-1394165319679. Node 192.168.1.202:50010
is expected to serve this storage.
org.apache.hadoop.hdfs.protocol.UnregisteredNodeException: Data node DatanodeRegistration(192.168.1.201, storageID=DS-1931411854-192.168.137.102-50010-1394165319679, infoPort=50075, ipcPort=50020, storageInfo=lv=-40;cid=cluster45;nsid=300226841;c=0) is attempting
to report storage ID DS-1931411854-192.168.137.102-50010-1394165319679. Node 192.168.1.202:50010 is expected to serve this storage.
这个时候,我们需要修改指定的datanode的current文件中的相应storageID的值,直接把它删除,这个时候,系统会动态新生成一个storageID,这样再次启动时就不会发生错误了。
5.3 Datanode 注册分析
DataNode节点向NameNode节点注册,一是告诉NameNode节点自己提 供服务的网络地址端口,二是获取NameNode节点对自己的管理与控制。Datanode 注册只会被两个地方调用, Datanode启动和心跳收到注册命令。DatanodeRegistration这个类主要用于,当Datanode向Namenode发送注册信息 时,它要向Namenode提供一些自己的注册信息。同时这个类中还可以设置它的父类就是DatanodeID的Name、infoPort、 storageInfo这些内容。name
表示DataNode节点提供数据传输/交换的服务地址端口,storageID表示DataNode节点的存储器在整个HDFS集群中的全局编 号,infoPort表示查询DataNode节点当前状态信息的端口号,ipcPort表示DataNode节点提供 ClientDatanodeProtocol服务端口号。
(1) datanode启动是会加载DataStorage,如果不存在则会format
(2)初次启动DataStorage的storageID是空的,所以会生成一个storageID
dnReg.storageID = "DS-" + rand + "-"+ ip + "-" + dnReg.getPort() + "-" + System.currentTimeMillis();
(3)注册成功后该storageID会写入磁盘,永久使用。
当NameNode节点收到某一个DataNode节点的注册请求之后,它会首先检查DataNode节点所运行的HDFS系统是否和自己是同一个版本号,然后才交给FSNamesystem来处理,源代码:
- /**
- * Datanode向Namenode注册,返回Namenode需要验证的有关Datanode的信息DatanodeRegistration的实例
- *
- * 检查该DataNode是否能接入到NameNode;
- * 准备应答,更新请求的DatanodeID;
- * 从datanodeMap(保存了StorageID >> DatanodeDescriptor的映射,用于保证DataNode使用的Storage的一致性)得到对应的DatanodeDescriptor,为nodeS;
- * 从Host2NodesMap(主机名到DatanodeDescriptor数组的映射)中获取DatanodeDescriptor,为nodeN;
- *
- * 如果nodeN!=null同时nodeS!=nodeN(后面的条件表明表明DataNode上使用的Storage发生变化),那么我们需要先在系统中删除nodeN(removeDatanode,下面再讨论),并在Host2NodesMap中删除nodeN;
- *
- * 如果nodeS存在,表明前面已经注册过,则:
- * 更新网络拓扑(保存在NetworkTopology),首先在NetworkTopology中删除nodeS,然后跟新nodeS的相关信息,调用resolveNetworkLocation,获得nodeS的位置,并从新加到NetworkTopology里;
- * 更新心跳信息(register也是心跳);
- *
- * 如果nodeS不存在,表明这是一个新注册的DataNode,执行
- * 如果注册信息的storageID为空,表明这是一个全新的DataNode,分配storageID;
- * 创建DatanodeDescriptor,调用resolveNetworkLocation,获得位置信息;
- * 调用unprotectedAddDatanode(后面分析)添加节点;
- * 添加节点到NetworkTopology中;
- * 添加到心跳数组中。
- *
- */
- public DatanodeRegistration register(DatanodeRegistration nodeReg
- ) throws IOException {
- verifyVersion(nodeReg.getVersion());
- namesystem.registerDatanode(nodeReg);
- return nodeReg;
- }
/** * Datanode向Namenode注册,返回Namenode需要验证的有关Datanode的信息DatanodeRegistration的实例 * * 检查该DataNode是否能接入到NameNode; * 准备应答,更新请求的DatanodeID; * 从datanodeMap(保存了StorageID >> DatanodeDescriptor的映射,用于保证DataNode使用的Storage的一致性)得到对应的DatanodeDescriptor,为nodeS; * 从Host2NodesMap(主机名到DatanodeDescriptor数组的映射)中获取DatanodeDescriptor,为nodeN; * * 如果nodeN!=null同时nodeS!=nodeN(后面的条件表明表明DataNode上使用的Storage发生变化),那么我们需要先在系统中删除nodeN(removeDatanode,下面再讨论),并在Host2NodesMap中删除nodeN; * * 如果nodeS存在,表明前面已经注册过,则: * 更新网络拓扑(保存在NetworkTopology),首先在NetworkTopology中删除nodeS,然后跟新nodeS的相关信息,调用resolveNetworkLocation,获得nodeS的位置,并从新加到NetworkTopology里; * 更新心跳信息(register也是心跳); * * 如果nodeS不存在,表明这是一个新注册的DataNode,执行 * 如果注册信息的storageID为空,表明这是一个全新的DataNode,分配storageID; * 创建DatanodeDescriptor,调用resolveNetworkLocation,获得位置信息; * 调用unprotectedAddDatanode(后面分析)添加节点; * 添加节点到NetworkTopology中; * 添加到心跳数组中。 * */ public DatanodeRegistration register(DatanodeRegistration nodeReg ) throws IOException { verifyVersion(nodeReg.getVersion()); namesystem.registerDatanode(nodeReg); return nodeReg; }
在 FSNamesystem中,会首先判断该DataNode是否被允许被连接到NameNode节点.在配置文件中,有这样两个选项:dfs.hosts 和dfs.hosts.exclude,它们的值对应的都是一个文件路径,dfs.hosts指向的文件是一个允许连接到NameNode节点的主机列 表,dfs.hosts.exclude指向的文件是一个不允许连接到NameNode节点的主机列表,所以在NameNode节点创建 FSNamesystem的时候,会根据配置文件中的选项值从文件中加载这些主机列表,这样就完成了检查。
如果这时发现DataNode的 storageID为空,会立马给它分配一个全局ID,然后,FSNamesystem会根据DataNode的ip地址把它映射到合适的机架 (rack)中.FSNamesystem还会对该DataNode的描述信息和它对应的storageID做一个映射并保存起来,之后,就把该 DataNode节点加入到heartbeats集合中,让HeartbeartMinitor后台线程来实时监测该DataNode节点当前是否还 alive,NameNode节点会把注册结果信息返回给DataNode节点。
关于注册时发生的特殊情况与处理:
1. 一台DataNode节点突然宕机了,然后立马恢复重启,NameNode节点也没有及时检测到,那么当这台重启的DataNode节点注册时,就会出现 nodeN == nodeS!= null,在这种情况下NameNode节点不会清除与该节点相关的信息,而只是会更新该节点的状态信息,同时重新解析它的ip地址到HDFS集群的网络 拓扑图中(这里之所以会重新解析ip地址,是因为在一个DataNode节点重启的过程中唯一可变的就是它所在的网络拓扑结构发生了变化);
2.一台DataNode节点在突然宕机或者认为stop之后,又马上重启,但是此时该 DataNode管理的存储器(逻辑磁盘)并不是之前管理的那一 个存储器了,那么该节点注册时就会出现nodeN != null 、nodeS != nodeN ,对于这种情况就相当于是该DataNode节点第一次注册,但是又必须要清除该DataNode节点上一次的注册信息,特别是Block与 DataNode之间的映射信息;
3.当一个DataNode节点由于更换了ip地址,所以它必须要重启并重新向 NameNode节点注册,此时该节点注册时就会出现nodeS != null、nodeS != nodeN(存储器没有变),此时并不需要清除该存储器原来所在的DataNode节点的相关注册信息,主要是Block和DataNode节点之间的映 射信息,而只需要更新原来与存储器绑定的DataNode节点的服务器地址信息,当然此时还必须要把新的DataNode节点的ip地址解析到HDFS集 群的网络拓扑图中。
http://www.cnblogs.com/kinglau/archive/2013/08/28/3287096.html
Hadoop的datanode无法启动
Hadoop的datanode无法启动
hdfs-site中配置的dfs.data.dir为/usr/local/hadoop/hdfs/data
用bin/hadoop start-all.sh启动Hdoop,用jps命令查看守护进程时,没有DataNode。
访问http://localhost:50070,点击页面中的Namenode logs链接,在logs页面点击hadoop-hadoop-datanode-ubuntu.log 链接,
发现在日志中有此提示:Invalid directory in dfs.data.dir: Incorrect permission for /usr/local/hadoop/hdfs/data, expected: rwxr-xr-x, while actual: rwxr-xrwx 。原因是data文件夹权限问题,执行:chmod g-w /usr/local/hadoop/hdfs/data,修改文件夹权限后,再次启动Hadoop,问题解决。