dyok 发表于 2017-12-17 06:49:56

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>
public static void main(String[] args) {  

// 将CompressionCodec实现的完全合格名称作为第一个命令行参数  
String codecClassname = args;
  
Class<?> codecClass =>  
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>
public static void main(String[] args) {
  
String uri
= args;  
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即可。
页: [1]
查看完整版本: Hadoop学习笔记(3) Hadoop I/O