Hadoop IO

来源:互联网 发布:vscode mysql 编辑:程序博客网 时间:2024/05/21 02:43
数据完整性:
HDFS会对写入的所有数据计算校验和,并在读取数据时验证校验和,针对每个有io.bytes.per.checksum指定字节的数据计算校验和
datanode负责在收到数据后存储该数据及验证校验和

客户端讲数据及其检验和发送到由一系列的datanode组成的管线(pipeline),管线中最后一个datanode负责验证校验和
每个datanode均持久保存一个用于验证的校验和日志,记录每个block的最后一次验证时间,客户端成功验证一个数据块后,会告诉这个datanode,datanode由此更新日志

每个datanode也会在一个后台的线程中运行DataBlockScanner,从而定期验证存储在这个datanode上的所有block,该措施是解决物理存储媒体上位损坏的有力措施

客户端在读取数据块时,检测到错误,具体处理流程:
客户端向namenode报告已损坏的数据块和datanode-->抛出ChecksumException异常-->namenode将这个数据块副本标记为已损坏-->安排这个数据块的一个副本复制到另一个datanode上-->已损坏的数据块副本删除

如果有一个已损坏的文件需要检查并决定如何处理:
1)java API: 在使用open读取文件之前,讲false传递给FileSystem对象的setVerifyChecksum()方法可以禁用校验和验证
2)命令模型:使用带-get选项的-ignoreCrc或者使用等价的-copyToLocal命令

如果想在一个应用中实现全局校验和验证,需要将fs.file.impl属性设置为org.apache.hadoop.fs.RawLocalFileSystem

压缩:
文件压缩对于处理大文件时相当重要,codec实现了一种压缩-解压缩算法,在Hadoop中一个对CompressionCodec接口的实现代表一个codec

CompressionCodec包含两个函数:
1)createOutputStream(OutputStream out)可以对写入输出流的数据进行压缩
2)createInputStream()可以对输入流中读取的数据进行解压缩

通过使用CompressionCodecFactory的getCodec(Path path)方法,CompressionCodecFactory提供了可以将文件扩展名映射到一个CompressionCodec

为了性能,最好使用原来类库来实现压缩和解压缩
默认情况下Hadoop会根据自身运行的平台搜索原生代码库,如果找到相应的代码库就会自动加载
压缩代码库的实现
压缩格式是否有java实现是否有原生类实现DEFAULT是否gzip是是bzip2是否LZO否是LZ4否是Snappy否是
如果使用的是原生代码库,并且需要在应用中执行大量压缩和解压缩操作,可以考虑使用CodecPool

Hadoop应用处理的数据集非常大,因此需要借助于压缩,使用哪种压缩格式与待处理的文件的大小,格式和所使用的工具有关
建议:按效率从高到低排列
1)使用容器文件格式,例如顺序文件,RCFile或者Avro数据文件,所有这些文件同时支持压缩和切分,通常最好与一个快速压缩工具联合使用,如LZO,LZ4或者Snappy
2)使用支持切分的压缩格式,例如bzip2或者使用通过索引实现切分的压缩格式,例如LZO
3)在应用中将文件切分成块,并使用任意一种压缩格式为每个数据块建立压缩文件,注:这种情况下需要合理选择数据块的大小,以确保压缩后的数据块的大小近似于HDFS块的大小
4)存储未经压缩的文件
注:对于大文件来说,不要使用不支持切分整个文件的压缩格式,因为会失去本地的数据特性,进而造成MapReduce应用效率低下

在MapReduce中使用压缩
压缩MapReduce作业的输出 方法:
1)在作业配置过程中mapred.output.compress属性设置为true和mapred.output.compression.codec属性设置为打算使用的压缩codec的类名
2)在代码中使用FileOutputFormat.setCompressOutput(job,true)FIleOutputFormat.setOutputCompressorClass(job,GzipCodec.class)

由于map任务的输出需要写到磁盘,并通过网络传输到reducer节点,所以如果使用LZO,LZ4或者Snappy这样的快速压缩方式,可以得到性能的提升


基于文件的数据结构
SequenceFile
SequenceFile类非常合适为二进制键值对提供一个持久的数据结构,SequenceFile也可以作为小文件的容器,通过SequenceFile类型将小文件包装起来

SequenceFile的写操作
通过createWriter()静态方法可以创建SequenceFile对象,并返回SequenceFile.writer实例,需要指定待写入的数据流(FileSystem、Path对象或FSDataOutputStream),Configuration对象以及键和值的类型
可以通过append()方法在文件末尾附加键值对

SequenceFile的读操作:
创建SequenceFile.Reader实例后,反复调用next()方法迭代读取记录,如果next()的是非null对象,则可以读取数据流中的键值对

在顺序文件中搜索给定位置的方法:
1)调用seek()方法,该方法将读指针指向文件中指定的位置,如果给定位置不是记录边界,调用next()方法就会报错
2)通过同步点查找记录边界,SequenceFile.Reader对象的sync(long position)方法可以将读取位置定为到position之后的下一个同步点SequenceFile.Writer对象有个sync方法,该方法可以在数据流的当前位置插入一个同步点

通过命令行接口显示Sequence:hadoop -text text.seq |head

SequenceFile的排序和合并
1)使用MapReduce可以对多个文件进行排序或合并
2)使用SequenceFile.Sorter类中的sort()和merge()

SequenceFile的格式:
顺序文件由文件头和随后的一条或多条记录组成,每个文件都有一个随机生成的同步标识,其值存放在文件头中,同步标识位于记录与记录之间,同步标识的额外存储开销要求小于1%,所以没有必要在每条记录末尾添加该标识。
记录的内部结构取决于是否启用压缩,如果已经启用,则取决于记录压缩数据块,如果没有启用压缩(默认)那么每条记录由记录长度,键长度,键和值组成;记录压缩格式与无压缩情况基本相同,只不过值是用文件头中定义的codec压缩的,注意,键没有压缩

块压缩是指一次性压缩多条记录,可以不断向数据块中压缩记录,直到块的字节数不小于io.seqfile.compress.blocksize属性中设置的字节数,默认为1MB。每个新块的开始处都需要插入一个同步标识。数据块的格式如下:字节数字段,压缩键长度、压缩键,压缩值长度,压缩值

MapFile
mapfile是已经排过序的SequenceFile,它有索引,可以按键查找,可以将MapFile视为java.util.Map的持久化形式
MapFile的写操作:
新建一个MapFile.Writer实例,然后调用append()方法顺序写入文件内容;键必须是WritableComparable类型的实例,值必须是Writable类型的实例
MapFile的读操作:
新建一个MapFile.Reader实例,然后调用next()方法,知道返回false,通过get()方法可以随机访问文件中的数据

MapFile的变种
1)SetFile是一种特殊的MapFile,用于存储Writable键的集合,键必须按照排好的顺序添加
2)ArrayFile中的键是一个整形,用于表示数据中元素的索引,而值是个Writable值
3)BloomMapFile:提供了一个get()的高性能实现,对于稀疏文件特别有用

将SequenceFile转换为MapFile方法:MapFile.fix()



































0 0
原创粉丝点击