hdfs FileStatus的accesstime的变更,hdfsaccesstime


背景:

hdfs文件系统有很多小文件,这些小文件会定期合并到大文件中,合并完成之后要删除这些小文件。但是有可能当前其他人正在读取这些小文件,此时如果将这些小文件删除,会导致当前用户无法正确获取到文件。

这一点hdfs做的有点恶心:最初我的理解是如果有线程A正在读取这个小文件,其他线程B删除这个小文件时应该会失败(至少应该要抛出异常)。但是测试发现不是这样的。实际的结果是:线程B默默的将小文件直接删除了,导致线程A只下载了这个文件的一部分,然后就卡在这里不动了。

 

针对这个问题的一个解决方案是:小文件被合并到大文件之后,保留30分钟后再删除,具体做法是通过FileStatus中的accesstime来获取上次的访问时间,如果当前时间减去accesstime超过了30分钟才真正的删除这个小文件。(也就是给30分钟的缓冲时间。小文件合并到到文件之后,以后新的请求都是从大文件中下载数据)

 

但是问题又出现了。

@Test
 public void fileStatusByRead() {

  // modification_time=1426037170715; access_time=1426037170138
  String desPath = "hdfs://******//8000000014268147637640-793038384000000014260371637637117";
  FSDataInputStream in = null;
  OutputStream outputStream = null;

  // 初始化主集群
  HDFSSystem hdfsSystem;
  try {
   hdfsSystem = new HDFSSystem();

   FileStatus fileStatus = hdfsSystem.getFileStatus(new Path(desPath));
   System.out.println("+++1:" + fileStatus.toString());                                           

   Thread.sleep(82 * 1000);

   in = hdfsSystem.open(new Path(desPath));

   long copySize = 8;
   outputStream = new FileOutputStream("D:\\input\\ttttt1.txt");

   // 读取数据
   IOUtils.copyBytes(in, outputStream, copySize, true);

   fileStatus = hdfsSystem.getFileStatus(new Path(desPath));
   System.out.println("+++2:" + fileStatus.toString());

  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 

测试发现System.out.println("+++1:" + fileStatus.toString()); 和System.out.println("+++2:" + fileStatus.toString());打印的时间居然一模一样

 

解决方法:

修改hdfs-site.xml中的

<property>
  <name>dfs.namenode.accesstime.precision</name>
  <value>3600000</value>
  <description>The access time for HDFS file is precise upto this value.
               The default value is 1 hour. Setting a value of 0 disables
               access times for HDFS.
  </description>
</property>

 

将默认的一小时改为10分钟。  但是这回带来一定的性能消耗。理想的解决办法是将文件的保留时间修改为1个小时或者2个小时。

相关内容

    暂无相关文章