Hadoop出现元数据不能更新且SNN合并失效

2019-03-28 13:47|来源: 网络

问题表现: NameNode 保存edits文件 停留在5.3号凌晨。SNN执行合并文件报 空指针错误,导致无法正常合并元数据

原因:要弄清原因首先需要清楚SNN合并流程,NN写editslog流程等等。简单说来如下:

1 在5.3号 SNN合并文件后并成功将合并的数据put到NN。当NN在关闭临时edit文件edit.new,打开edits文件时报错:unable to open

2 正常情况下,打开edits文件后,会将edits输出流加入前面已经清空的edits输出流列表。在1 失败下,该操作未做,所以edits输出流列表为空表对象

3 打开失败下,会将失败的路径自动移除掉,以便后面的自动尝试恢复。同时自动尝试恢复是在SNN合并文件时出发。但是咱们的情况是2个edits路径全部失败,导致 路径集合为null。

4 新的SNN合并请求过来后会先得到存储路径集合,此时报Null退出 。

5 对于文件操作的日志,因为2操作没有执行,没有可用的edits输出流列表,所以直接往下执行其他操作,导致edits文件也不再更新。

解决思路:

1 因为NN不再更新edits文件,SNN也无法合并Img,所以以前NN保存的元数据无法使用。所以必须恢复元数据到最新。这可以通过hdfs提供的api导出hdfs目录元数据并保存。

这个操作必须在安全模式下执行。

2 从上面5点看,很多操作时由于打不开edit后导致的edits输出流列表为空表(不是Null)和NN的元数据存储路径为Null

3 恢复edits输出流列表,才能让NN正常写edits,这个操作可以调用hdfs提供的api实现。

4 恢复NN的元数据存储路径也可以调用hdfs提供的api重新设置。

解决方案:

1 让集群进入安全模式,使用导出元数据的jsp ,导出最新元数据,停止集群,,拷贝新的元数据替换旧的元数据后重启集群。

2 让集群进入安全模式,使用导出元数据的jsp ,导出最新元数据,拷贝新的元数据替换旧的元数据。恢复edits流列表,恢复NN的元数据存储路径列表,离开安全模式。(测试正常,但没在线上应用)

附件:

1 导出元数据的jsp:

 
  1. <%@ page  
  2.   contentType="text/html; charset=UTF-8"  
  3.   isThreadSafe="false"  
  4.   import="java.io.*"  
  5.   import="java.lang.reflect.*"  
  6.   import="org.apache.Hadoop.hdfs.*"  
  7.   import="org.apache.hadoop.hdfs.server.namenode.*"  
  8.   import="org.apache.hadoop.hdfs.server.common.Storage.StorageDirectory"  
  9.   import="org.apache.hadoop.hdfs.server.common.Storage.StorageDirType"  
  10. %>  
  11. <%  
  12. String path = request.getParameter("dir");  
  13. if (path == null) {  
  14.   throw new IllegalArgumentException("specify dir parameter");  
  15. }  
  16. File dir = new File(path);  
  17. if (!dir.exists()) {  
  18.   dir.mkdir();  
  19. }  
  20.   
  21. NameNode nn = (NameNode)application.getAttribute("name.node");  
  22. if (!nn.isInSafeMode()) {  
  23.   throw new IllegalStateException("not in safe mode");  
  24. }  
  25.   
  26. // Use reflection to find saveCurrent()   
  27. FSImage image = nn.getFSImage();  
  28. Method m = FSImage.class.getDeclaredMethod("saveCurrent", StorageDirectory.class);  
  29. m.setAccessible(true);  
  30.   
  31. // Use reflection to find the IMAGE_AND_EDITS enum, since it's package-protected   
  32. Class c = Class.forName("org.apache.hadoop.hdfs.server.namenode.FSImage$NameNodeDirType");  
  33. StorageDirType[] constants = (StorageDirType[])c.getEnumConstants();  
  34.   
  35. StorageDirType t = null;  
  36. for (StorageDirType sdt : constants) {  
  37.   if (sdt.toString().equals("IMAGE_AND_EDITS")) {  
  38.     t = sdt;  
  39.   }  
  40. }  
  41. if (t == null) {  
  42.   throw new IllegalStateException("no type");  
  43. }  
  44.   
  45. // Actually save   
  46. StorageDirectory sd = image.new StorageDirectory(dir, t);  
  47. m.invoke(image, sd);  
  48. %>  
  49. Saved image to <%= sd.getCurrentDir() %>  

2 查看 edit流列表及存储路径集合及其他对象jsp:

 
  1. <%@ page  
  2.   contentType="text/html; charset=UTF-8"  
  3.   isThreadSafe="false"  
  4.   import="java.io.*"  
  5.   import="java.util.*"  
  6.   import="java.lang.reflect.*"  
  7.   import="org.apache.hadoop.hdfs.*"  
  8.   import="org.apache.hadoop.hdfs.server.namenode.*"  
  9.   import="org.apache.hadoop.hdfs.server.common.Storage.StorageDirectory"  
  10.   import="org.apache.hadoop.hdfs.server.common.Storage.StorageDirType"  
  11. %>  
  12.   
  13. <%  
  14.    NameNode nn = (NameNode)application.getAttribute("name.node");  
  15.      
  16.    out.println("namenode="+nn.toString());  
  17.    final FSImage nnImage = (FSImage)application.getAttribute("name.system.image");  
  18.    out.println("storagedirs="+nnImage.listStorageDirectories());  
  19.   Method m = FSImage.class.getDeclaredMethod("getFsImageName"null);  
  20.   m.setAccessible(true);  
  21.   out.println("nnImage.getFsImageName()="+m.invoke(nnImage,null));  
  22.    
  23.    out.println("httpserver name.system.image="+nnImage.toString());  
  24.    out.println("getFsImage from nn="+nn.getFSImage());  
  25.   out.println("<br/>");  
  26.    File eFile=new File("/data0/hadoop/hdfs/name/current/edits");  
  27.    RandomAccessFile rp = new RandomAccessFile(eFile, "rw");  
  28.    FileOutputStream  fp = new FileOutputStream(rp.getFD());  
  29.   // FSEditLog.EditLogOutputStream eStream = new FSEditLog.EditLogFileOutputStream(eFile);   
  30.    out.println("fileoutputstream="+fp.toString());     
  31.   
  32.    out.println("<br/>");  
  33.   m = FSImage.class.getDeclaredMethod("getRemovedStorageDirs"null);  
  34.   m.setAccessible(true);  
  35.  List<StorageDirectory> list=(List<StorageDirectory>)m.invoke(nnImage,null);  
  36.   out.println("removedStorageDirs.size="+list.size());  
  37.   for(StorageDirectory dir:list)  
  38.    out.println("removeddir="+dir.getRoot().getPath().toString());  
  39.   
  40. out.println("<br/>");  
  41. FSNamesystem fsNamesystem=nn.getNamesystem();  
  42. Method mm = FSNamesystem.class.getDeclaredMethod("getEditLog"null);  
  43. mm.setAccessible(true);  
  44. FSEditLog editlog=(FSEditLog)mm.invoke(fsNamesystem,null);  
  45. out.println("nn's editlog="+editlog.toString());  
  46.   
  47.   
  48. Method mm1 = FSEditLog.class.getDeclaredMethod("getNumEditStreams"null);  
  49. mm1.setAccessible(true);  
  50. out.println("getNumEditStreams="+mm1.invoke(editlog,null));  
  51. %>  

相关问答

更多
  • 如果是a b c三个单独的索引,你那个语句不会失效。单独索引一般会在模糊查询失效 但是如果是(a,b,c)复合索引的话,是根据最左前缀匹配原则,失效的语句为where 条件包括: 1. where b=2 and c=3 2. where a=1 and c=3 3. where 单独的b=2 或者单独的c=3 只有当a,ab,abc,才有效
  • 使用服务器端副本更新元数据: blobStore.copyBlob(containerName, blobName, containerName, blobName, CopyOptions.builder() .contentMetadata(...) .userMetadata(...) .build()); Use a server-side copy to update metadata: blobStore.copyBlob(containerNa ...
  • 我认为以下解释可以帮助您更好地理解HDFS架构。 您可以将Name节点视为FAT(文件分配表)+目录数据和数据节点为哑块设备。 当您想要从常规文件系统中读取文件时,您应该转到目录,然后转到FAT,获取所有相关块的位置并读取它们。 HDFS也是如此。 当您想要读取文件时,您将转到Namenode,获取给定文件所具有的列表块。 有关块的信息将包含此信息所在的数据节点列表。 之后,您将转到datanode并从中获取相关块。 I think the following explanation can help yo ...
  • 这有点棘手,所以我猜别人可能会有同样的问题,所以我在这里分享一些代码,并希望有人从中得到任何帮助:-)我在下面的代码中最重要的部分: public function __construct() { add_action( 'post_updated', array( $this, 'datachangecheck' ), 10, 3 ); } /* * datachangecheck * * This functio ...
  • 小于HDFS块大小(默认为64兆字节)的文件成为块的一部分,是的。 但是在某些情况下,诸如此类的小文件可能仍然会损害您的性能,例如,如果您有很多这些小文件并且在它们上运行MapReduce作业。 Vanilla Hadoop与Bigtable无关,HDFS块与平板电脑无法真正对比。 虽然Hadoop的HDFS模块不了解他们持有的数据,但Bigtable平板电脑具有数据感知能力。 A file which is less than the block size of HDFS (default 64 mega ...
  • appendToFile修改HDFS中的现有文件,因此只需要将新数据流式传输/写入文件系统。 put重写整个文件,因此需要将整个新版本的文件流式传输/写入文件系统。 如果您只是附加到文件(即将日志添加到文件末尾),则应该使用appendToFile 。 如果这是你的用例,这个功能会更快。 如果文件的变化不仅仅是简单的追加到最后,你应该使用put (较慢但你不会丢失数据或破坏你的文件)。 appendToFile modifies the existing file in HDFS, so only the ...
  • 不可以。如果不实际交换数据本身,您不能指望进行数据交换。 没有同步“异步”Javascript调用这样的东西。 我认为你的意思很好,但你应该尝试更准确。 无论如何,在这种情况下速度的问题到底是什么? 你为什么要关心返回服务器的POST需要300毫秒或600毫秒或者其他什么......如果需要3000毫秒,你有一个搞砸的服务器,这是你的问题......不是XHR。 No. You cannot expect an exchange of data to occur without actually excha ...
  • 对不起,如果该声明有点误导。 元数据更新可通过soda-java库正式获得,也可通过sodapy非正式sodapy 。 为了正确理解,您希望以编程方式在一组数据集上更新标记集,如果我已正确阅读您的配置文件,您似乎可以作为数据发布者访问Socrata平台。 正确? Sorry if that statement is a little misleading. Metadata update is available officially through the soda-java library and un ...
  • 如果您想更新com.netflix.appinfo.ApplicationInfoManager客户端的任何元数据,只需使用com.netflix.appinfo.ApplicationInfoManager对象并调用registerAppMetadata(Map) 。 如果是这样,此信息通常很快或至少在30秒内在Eureka Server中更新。您可以使用DI获取ApplicationInfoManger的实例。 如果要更新其他服务实例的元数据,只需调用以下REST API ...
  • 这就是我的理解。 如果你仔细阅读,重要的是要记住: 请注意,这不会改变轮数; 它只是一种优化,可以最大限度地减少写入磁盘的数据量,因为最后一轮总是直接合并到reduce中。 无论是否进行优化,合并轮次数都保持不变 (第一种情况下为5次,第二种情况下为4次)。 第一种情况:50个文件合并到最后5个,然后直接进入“减少”阶段(总轮数为5 + 1 = 6) 第二种情况:34个文件合并到最后4个文件中,其余6个文件直接从内存中读取并送入“减少”阶段(总轮数为4 + 1 = 5) 在这两种情况下,合并轮次数由配置ma ...