HDFS中atime与mtime解析
先来了解下Linux中atime和mtime区别:
atime:access time即访问时间
mtime:modify time即修改时间,这里指文件内容的修改。(经常和atime与mtime一起谈到的还有ctime,这里不展开,有兴趣的可以goolge)
这里需要注意的是有的系统可能为了性能上的优化,atime并不是实时更新,此时查看atime并没有得到想要的效果。
Linux atime修改策略与mount有关,可选的值有noatime
、relatime
和strictatime
。
- noatime
atime不会被更新,即使修改了文件内容 - relatime
- 如果一个文件的atime比ctime或mtime更早,此时你去读取了该文件,atime才会被更新为当前时间。
- atime比现在早一天,那么atime在文件读取时会被更新
- strictatime
atime在文件每次被读取时,都能够被更新
HDFS中atime和mtime
了解了Linux中的atime与mtime,我们来了解下HDFS中的这两个值的变化规则。
在看代码之前,先想下atime和mtime有可能在哪些地方会修改,
hdfs底层api对文件都有哪些操作?无非就是读写两种操作,读肯定修改的是atime,写修改的是mtime,是否修改atime还得确认。
这里我们还漏掉一种操作,那就是mv。
先来看下atime
atime
去年写过一篇文章[HDFS read解析(一)之Open文件流](http://bigdatadecode.top/HDFS read解析.html)介绍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小时。
这里遗留两个问题
1、新建文件时atime如何赋值
2、修改文件内容时atime如何赋值
关于这个两个问题我在下一节在写流程中解答。请继续向下看
mtime
同样去年也写过一篇关于写的文章[HDFS write解析](http://bigdatadecode.top/HDFS write解析.html)介绍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、两次读间隔大于默认的1小时时,更新atime。默认间隔通过dfs.namenode.accesstime.precision
控制。
2、新建一个文件时atime赋值为当前时间(注意,当关闭一个文件时atime不会修改)
mtime
1、新建一个文件时mtime赋值为当前时间(同时会修改atime)
2、关闭一个文件时mtime赋值为当前时间(此时并不会修改atime)