HDFS文件写入FSDataOutputStream中的持久化hsync()不起作用详解

来源:互联网 发布:svn nginx http 访问 编辑:程序博客网 时间:2024/06/10 05:12

问题说明

近期项目中用到实时抽取ActiveMQ中的爬虫数据到HIVE表中,但是在持久化数据到HDFS的时候,发现FSDataOutputStream.hsync()不能实时持久化,只能持久化第一条数据。
从一些文章中了解到,只有当HDFS中的block达到128M时,才可以使block处于completed状态,即持久化显示查到,故在代码测试中如果将流close掉,即可实现持久化,但是与业务场景不服;


拓展HDFS的hflush,hsync和close区别

hflush: 语义是保证flush的数据被新的reader读到,但是不保证数据被datanode持久化。
hsync: 与hflush几乎一样,不同的是hsync保证数据被datanode持久化。
close: 关闭文件,除了做到以上2点,还保证文件的所有block处于completed状态,并且将文件置为closed。


解决方法

查看源码,发现FSDataOuputStream中有一个方法getWrappedStream(),返回DFSOutputStream对象;
在DFSOutputStream中有一个方法:hsync(EnumSet syncFlags);

这里写图片描述

从方法说明中可以了解到,决定是否更新block的长度标识(即持久化);
自己建一个EnumSet 参数放进去,其中SyncFlag中含有一个默认值“UPDATE_LENGTH”,其中的说明可以解释;

这里写图片描述


解决代码

// 实时持久化处理DFSOutputStream dfsOutputStream = (DFSOutputStream) outputStream.getWrappedStream();EnumSet<HdfsDataOutputStream.SyncFlag> syncFlags = EnumSet.of(HdfsDataOutputStream.SyncFlag.UPDATE_LENGTH);dfsOutputStream.hsync(syncFlags);