Hadoop学习笔记(3) Hadoop I/O

1. HDFS的数据完整性

  HDFS会对写入的所有数据计算校验和,并在读取数据时验证校验和。datanode负责在验证收到的数据后存储数据及其校验和。正在写数据的客户端将数据及其校验和发送到由一系列datanode组成的管线,管线中的最后一个datanode负责验证校验和。如果datanode检测到错误,客户端便会收到一个ChecksumException异常。

  客户端从datanode读取数据时,也会验证校验和,将它们与datanode中存储的校验和进行比较。每个datanode均持久保存有一个用于验证的校验和日志,所以它知道每个数据块的最后一次验证时间。客户端成功验证一个数据块后,会告诉这个datanode,datanode由此更新日志。

  不只是客户端在读取数据块时会验证校验和,每个datanode也会在后台线程中运行一个DataBlockScanner,从而定期验证存储在这个datanode上的所有数据块。

  客户端在读取数据块时,如果监测到错误,就像namenode报告已损坏的数据块及其正在尝试读操作的这个datanode,最后才抛出ChecksunException异常。namenode将这个已损坏的数据块的复本标记为已损坏,之后安排这个数据块的一个复本复制到另一个datanode,如此一来,数据块的复本因子又回到期望水平。此后,已损坏的数据块复本便被删除。

  禁用校验和的方法:在的、使用open()方法读取文件之前,将false值传递给FileSystem对象的setVerifyChecksum()方法。

  (1) LocalFileSystem执行客户端的校验和验证,意味着在你写入名为filename的文件时,客户端会在包含每个文件块校验和的同一个目录内新建一个名为filename.crc的隐藏文件。读取文件时需要验证校验和,若检测到错误,LocalFileSystem将抛出ChecksumException异常。

  禁用校验和,可使用RawLocalFileSystem代替LocalFileSystem。

  (2) ChecksumFileSystem

  LocalFileSystem通过ChecksumFileSystem来完成校验,有了该类,向其他文件系统加入校验和就非常简单。

2. 压缩

  压缩格式:

  所有压缩算法都需要权衡空间/时间:压缩和解压缩速度更快,其代价通常是只能节省少量的空间。表中的压缩工具提供9个不同的选项来控制压缩时间时必须考虑的权衡:-1为优化压缩速度,-9为优化压缩时间。

  codec实现了一种压缩-解压缩算法。在Hadoop中,一个对CompressionCodec接口的实现代表一个codec。

  (1) 通过CompressionCodec对数据流进行压缩和解压缩

  如果要对写入输出数据流的数据进行压缩,可用createOutputStream(OutputStream out)方法新建一个CompressOutputStrean对象,相反,对输入数据流中读取的数据进行解压缩时,调用createInpueStream(InputStream in)获取CompressionInputStream。

public class StreamCompressor{
    public static void main(String[] args) {
        // 将CompressionCodec实现的完全合格名称作为第一个命令行参数
        String codecClassname = args[0];
        Class<?> codecClass = Class.forName(codecClassname);
        Configuration conf = new Configuration();
        
        // 使用ReflectionUtils构建一个新的codec实例
        CompressionCodec codec = (CompressionCodec)ReflectUtils.newInstance(codecClass,conf);
        // 在System.out上包裹一个压缩方法。
        CompressionOutputStream out = codec.createOutputStream(System.out);
        IOUtils.copyBytes(System.in,out,4096,false);
     // 调用finish()方法,要求压缩方法完成到压缩数据流的写操作,但不关闭这个数据流 out.finish(); } }

 

  例:通过GzipCodec的Stream对象对字符串"Text"进行压缩,然后使用gunzip从标准输入中对它进行读取并解压缩:

  % echo "Text" | hadoop StreamCompressor org.apache.hadoop.io.compress.GzipCodec | gunzip

  (2) 通过CompressionCodecFactory推断CompressCodec

  CompressionCodecFactory的getCodec()方法可以将文件扩展名映射到一个CompressionCodec,该方法去文件Path对象欧威参数。

  例:由文件扩展名推断而来的codec对文件进行解压缩

public class FileDecompressor{
    public static void main(String[] args) {
        String uri = args[0];
        Configuration conf = new Configuration();
        FileSystem fs = FileSyste.get(URI.create(uri),conf);
        
        Path inputPath = new Path(uri);
        CompressionCodecFactory factory = new CompressionCodecFactory(conf);
        CompressionCodec codec = factory.getCodec(inputPath);
        if(codec == null){
            System.err.println("No codec found for "+uri);
            System.exit(1);
        }
        
     // 一旦找到对应的codec,便去除文件扩展名行成输出文件名 String outputUri
= CompressionCodecFactory.removeSuffix(uri,codec.getDefaultExtension()); InputStream in = null; OutputStream out = null; try{ in = codec.createInputStream(fs.open(inputPath)); out = fs.create(new Path(outputUri)); IOUtils.copyBytes(in,out,conf); }finally{ IOUtils.closeStream(in); IOUtils.closeStream(out); } } }

 

  例:一个名为file.gz的文件可以通过下面的程序压缩为名为file的文件:

  % hadoop FileDecompressor file.gz

  下表为压缩codec的属性:

  

  (3) 原生类库 

  原生类库可以提供压缩/解压缩性能。注意:并非所有格式都有原生实现。

  可以通过Java系统的java.library.path属性指定原生代码库。默认情况下,Hadoop会根据自身运行的平台搜索原生代码库。禁用原生代码库,将属性hadoop.native.lib的值设置成false即可。

转载于:https://www.cnblogs.com/mengrennwpu/p/4896554.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值