HDFS 中 atime 和 mtime
转载来源
1 | 作者:混绅士 |
前言
如果不知道 atime、mtime 的建议先了解下 Linux 中 atime 和 mtime,这样有助于学习 HDFS 中 atime 与 mtime
查看
转载文章中未介绍如何查看 HDFS atime、mtime,因此说明下。
跟 Linux 一样,也是使用 stat 命令来查看
用法: hadoop fs -stat [format] <path> ...
以指定的格式打印有关
处的文件/目录的统计信息。格式接受八进制(%a)和符号(%A),字节(%b)文件大小,类型(%F),所有者组名称(%g),名称(%n),块大小(%o),复制(%r),
所有者用户名(%u),访问日期(%x,%X)和修改日期(%y,%Y)。%x和%y将UTC日期显示为“yyyy-MM-dd HH:mm:ss”,并且%X和%Y显示自1970年1月1日UTC以来的毫秒数。如果未指定格式,则默认使用%y。 —— https://www.jianshu.com/p/49d89c197310
如查看 HBase 根目录
1 | $ hadoop fs -stat "type:%F perm:%a %u:%g size:%b mtime:%y atime:%x name:%n" /hbase |
分析
先来了解下 HDFS 中的这 atime 与 mtime 的变化规则
在看代码之前,先想下 atime 和 mtime 有可能在哪些地方会修改
hdfs底层api对文件都有哪些操作?
无非就是读写两种操作,读肯定修改的是atime,写修改的是mtime,是否修改atime还得确认。
这里我们还漏掉一种操作,那就是mv。
atime
去年写过一篇文章 HDFS read解析(一)之Open文件流介绍HDFS读操作流程,这里就不再累赘了,直接贴出关键代码。(有兴趣的同学可以自行查看)
这里还是简单说下读的流程:客户端向NN发起一个读请求,NN将相关的block信息返回给客户端,客户端再与对应的DN建立连接读取信息。
在这个过程中,先与NN交互然后再与DN交互,那么每个文件的atime相关元数据信息都存在NN中,那么atime相关的修改也肯定发生在与NN交互的这个过程中。
从之前的文章中可知入口函数是 FSNamesystem.getBlockLocations
,关键代码如下
1 | LocatedBlocks getBlockLocations(String clientMachine, String srcArg, |
res.updateAccessTime()
决定了是否更新atime,其值是在getBlockLocationsInt中赋值的,代码如下
1 | boolean updateAccessTime = isAccessTimeSupported() && !isInSafeMode() |
其中关键的因素是isAccessTimeSupported()
和getAccessTimePrecision()
,这个两个方法都与accessTimePrecision
有关,
此值是由dfs.namenode.accesstime.precision
设置的,默认是3600000。
当此值大于0,isAccessTimeSupported()
返回true,getAccessTimePrecision()
得到的值是dfs.namenode.accesstime.precision
的值。
从上述代码中可以看出更新atime的一个条件是两次读取间隔相隔dfs.namenode.accesstime.precision
秒,默认是1小时。
这里遗留两个问题:
- 新建文件时atime如何赋值
- 修改文件内容时atime如何赋值
关于这个两个问题我在下一节在写流程中解答。请继续向下看
mtime
同样去年也写过一篇关于写的文章HDFS write解析介绍HDFS读操作流程,这里就不再累赘了,直接贴出关键代码。(有兴趣的同学可以自行查看)
写相关的操作包括create、close和append
写文件有两种方式,一种是调用create(Path)
方法,另一种是调用append(Path)
方法
create
通过调用create(Path)
,最终会调用FSDirectory.addFile
方法,
在此方法中会new一个INodeFile
,此时会设置 mtime 和 atime 为同一个值,代码如下:
1 | INodesInPath addFile(INodesInPath existing, String localName, PermissionStatus |
有打开一个文件就有关闭一个文件,接下来看下关闭文件时 atime 和 mtime 会有什么变化。
close
closeFile()
在finalizeINodeFileUnderConstruction
中调用,在此方法中会设置mtime,看下代码
1 | private void finalizeINodeFileUnderConstruction(String src, |
从代码中可以看出,close文件时只对mtime进行了修改。
append
append只是打开一个文件流,并不会修改mtime或者atime,只是在close的时候修改mtime
结论
atime
- 两次读间隔大于默认的1小时时,更新atime。默认间隔通过
dfs.namenode.accesstime.precision
控制。 - 新建一个文件时atime赋值为当前时间(注意,当关闭一个文件时atime不会修改)
mtime
- 新建一个文件时mtime赋值为当前时间(同时会修改atime)
- 关闭一个文件时mtime赋值为当前时间(此时并不会修改atime)