Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hadoop hsync()不适用于SequenceFile Writer_Hadoop_Hdfs_Sequencefile - Fatal编程技术网

Hadoop hsync()不适用于SequenceFile Writer

Hadoop hsync()不适用于SequenceFile Writer,hadoop,hdfs,sequencefile,Hadoop,Hdfs,Sequencefile,我有一个小程序,每秒将10条记录写入HDFS上的块压缩SequenceFile,然后每5分钟运行一次sync(),以确保超过5分钟的所有内容都可以处理 因为我的代码有很多行,所以我只提取了重要的部分: // initialize Configuration hdfsConfig = new Configuration(); CompressionCodecFactory codecFactory = new CompressionCodecFactory(hdfsConfig); Compr

我有一个小程序,每秒将10条记录写入HDFS上的块压缩SequenceFile,然后每5分钟运行一次sync(),以确保超过5分钟的所有内容都可以处理

因为我的代码有很多行,所以我只提取了重要的部分:

// initialize

Configuration hdfsConfig = new Configuration();

CompressionCodecFactory codecFactory = new CompressionCodecFactory(hdfsConfig);
CompressionCodec compressionCodec = codecFactory.getCodecByName("default");

SequenceFile.Writer writer = SequenceFile.createWriter(
    hdfsConfig,
    SequenceFile.Writer.file(path),
    SequenceFile.Writer.keyClass(LongWritable.class),
    SequenceFile.Writer.valueClass(Text.class),
    SequenceFile.Writer.compression(SequenceFile.CompressionType.BLOCK;, compressionCodec)
);

// ...


// append

LongWritable key = new LongWritable((new Date).getTime());
Text val = new Text("Some value");
writer.append(key, val);

// ...

// then every 5 minutes...

logger.info("about to sync...");
writer.hsync();
logger.info("synced!");
仅从日志来看,同步操作似乎与预期一样工作,但是HDFS上的文件仍然很小。一段时间后,可能会添加一些标题和事件,但频率甚至接近I hsync()。文件关闭后,所有内容都将立即刷新

在每次预期的同步之后,您也尝试手动检查文件内容以查看数据是否存在,但是,文件在此处也显示为空: hdfs dfs-文本文件名

writer.hsync()不起作用有什么已知的原因吗?如果有,有什么解决办法吗

此问题的其他测试用例:

import java.util.HashMap;
import java.util.Map;
import java.util.Date;
import java.util.Calendar;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.compress.CompressionCodecFactory;
import org.apache.hadoop.io.compress.CompressionCodec;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;

import java.io.IOException;

import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class WriteTest {
    private static final Logger LOG = LoggerFactory.getLogger(WriteTest.class);

    public static void main(String[] args) throws Exception {

        SequenceFile.CompressionType compressionType = SequenceFile.CompressionType.RECORD;
        CompressionCodec compressionCodec;
        String compressionCodecStr = "default";
        CompressionCodecFactory codecFactory;
        Configuration hdfsConfig = new Configuration();

        codecFactory = new CompressionCodecFactory(hdfsConfig);
        compressionCodec = codecFactory.getCodecByName(compressionCodecStr);

        String hdfsURL = "hdfs://10.0.0.1/writetest/";

        Date date = new Date();

        Path path = new Path(
            hdfsURL,
            "testfile" + date.getTime()
        );

        SequenceFile.Writer writer = SequenceFile.createWriter(
            hdfsConfig,
            SequenceFile.Writer.keyClass(LongWritable.class),
            SequenceFile.Writer.valueClass(Text.class),
            SequenceFile.Writer.compression(compressionType, compressionCodec),
            SequenceFile.Writer.file(path)
        );

        for(int i=0;i<10000000;i++) {

            Text value = new Text("New value!");
            LongWritable key = new LongWritable(date.getTime());

            writer.append(key, value);
            writer.hsync();

            Thread.sleep(1000);
        }

        writer.close();
    }
}
import java.util.HashMap;
导入java.util.Map;
导入java.util.Date;
导入java.util.Calendar;
导入org.apache.hadoop.conf.Configuration;
导入org.apache.hadoop.fs.FileSystem;
导入org.apache.hadoop.fs.Path;
导入org.apache.hadoop.fs.FSDataOutputStream;
导入org.apache.hadoop.io.SequenceFile;
导入org.apache.hadoop.io.compress.CompressionCodecFactory;
导入org.apache.hadoop.io.compress.CompressionCodec;
导入org.apache.hadoop.io.LongWritable;
导入org.apache.hadoop.io.NullWritable;
导入org.apache.hadoop.io.Text;
导入org.apache.hadoop.io.writeable;
导入java.io.IOException;
导入java.text.simpleDataFormat;
导入java.text.DateFormat;
导入java.text.ParseException;
导入java.util.Calendar;
导入java.util.Date;
导入java.util.Locale;
公共类WriteTest{
私有静态最终记录器LOG=LoggerFactory.getLogger(WriteTest.class);
公共静态void main(字符串[]args)引发异常{
SequenceFile.CompressionType CompressionType=SequenceFile.CompressionType.RECORD;
压缩编解码器压缩编解码器;
字符串压缩codecstr=“默认”;
压缩工厂;
配置hdfsConfig=新配置();
codecFactory=新的压缩codecFactory(hdfsConfig);
compressionCodec=codecFactory.getCodecByName(compressionCodecStr);
字符串hdfsURL=”hdfs://10.0.0.1/writetest/";
日期=新日期();
路径=新路径(
hdfsURL,
“testfile”+date.getTime()
);
SequenceFile.Writer Writer=SequenceFile.createWriter(
hdfsConfig,
SequenceFile.Writer.keyClass(LongWritable.class),
SequenceFile.Writer.valueClass(Text.class),
SequenceFile.Writer.compression(压缩类型,压缩编解码器),
SequenceFile.Writer.file(路径)
);

对于(int i=0;i,这里有多个问题

  • 块压缩
  • 当您对序列文件使用块压缩时,这意味着当达到限制或手动调用
    sync
    时,许多条目将在内存中缓冲,然后以块压缩形式写入

    当您在writer上调用
    hsync
    时,它会在其底层
    FSDataOutputStream
    上调用
    hsync
    。但是,这不会写入内存中压缩缓冲区中的数据。因此,要将数据可靠地发送到数据节点,您必须先调用
    sync
    ,然后调用
    hsync

    请注意,这样做意味着发送到Datanode的块压缩部分包含的条目比通常更少。这对压缩质量有负面影响,可能会导致更多的光盘使用。(我想这就是
    hsync
    不在内部调用
    sync
    的原因。)

  • 报告给Namenode的文件大小
  • 调用
    fsync
    会将数据发送到Datanodes,但不会向namenode报告新的文件大小。关于这一点的技术讨论可以找到,并且可以找到。显然,每次更新长度都会对性能造成不利影响。
    hsync
    有一个特殊版本,允许更新namenode信息,但它不是exposed by
    SequenceFile.Writer

        * @param syncFlags
        *          Indicate the semantic of the sync. Currently used to specify
        *          whether or not to update the block length in NameNode.
        */
        public void hsync(EnumSet<SyncFlag> syncFlags) throws IOException {
            flushOrSync(true, syncFlags);
        }
    
    *@param syncFlags
    *指示同步的语义。当前用于指定
    *是否更新NameNode中的块长度。
    */
    public void hsync(EnumSet syncFlags)引发IOException{
    flushOrSync(true,syncFlags);
    }
    
    一方面,大小问题意味着,即使某些工具报告的文件大小没有改变,数据仍然安全地到达了Datanodes,并且在其上打开InputStream时可以读取。另一方面,SequenceFile.Reader for compression type
    Record
    None
    中存在缺陷。使用这些压缩类型读取器使用长度信息确定读取的距离。由于此长度信息未由
    hsync
    更新,因此即使数据实际可用,它也会错误地停止读取。
    Block
    压缩读取显然不使用长度信息,并且不会出现此错误