第五章 HADOOP I/0 第一节 数据完整性

        HADOOP自带了一组原始的数据I/O。其中一些技术比HADOOP更通用,如数据完整性和压缩,

但在处理TB级的数据时需要特别考虑。其它的HADOOP工具或API是开发分布式系统的构建块,如

序列化框架和磁盘上的数据结构。


数据完整性

        HADOOP用户期望在存储或处理数据时没有丢失或损坏。然而,每一个磁盘或网络的读写的IO

操作都可能导致数据错误,当流经系统的海量数量和HADOOP的处理极限一样大的,数据损坏的

机会是很高的。

        通常的数据校验方法是在数据第一次进入系统时计算数据的校验和,当它在一个不可信的通道

传播时有可能导致数据损坏会再次校验。如果新生成的数据的检验和与原始的不能精确匹配,那么就

认为它是损坏的。这个技术没有提供修复数据的方法----它仅仅检测错误(这是为什么不使用低端硬件

的原因;尤其是要使用ECC内存)。注意,有可能是校验和损坏而不是数据损坏,但是这个机率很小,

因为校验和比数据小的多。

        一个普遍使用的检测错误的是CRC-32(32-bit cyclic redundancy check),它对任意大小的输入

产生一个32位的校验和。CRC-32用在HADOOP的ChecksumFileSystem中用来做校验和处理,同时

HDFS使用一个更有效的变体叫CRC-32C。


HDFS中的数据完整性

        HDFS校验所有写入/读取的数据。每dfs.bytes-perchecksum的byte数据会产生一个单独的检验和。

默认的是512byte,因为CRC-32C校验和长度是4byte,存储开销小于1%。

        datanode在接收数据存储之前,负责检查数据及校验。这适用于他们从客户端接收的数据和在复制

时从其它datanode接收的数据。客户端把数据发送到datanode组成的pipeline(第三章解释过),pipeline

中的最后一个datanode检查校验和。如果这个datanode检测到错误,客户端接收到一个IOException的

子类,需要它处理(例如,重新执行操作)。

        当客户端从datanode读取数据时,它们也会检查校验和,把它与存储了这个数据的datanode比较。

每一个datanode都保存了校验和验证日志,所以它知道它的每一个block的最后验证时间。当客户端验证

成功一个block,它告诉datanode,datanode会更新它的日志。像这样保存统计信息在检测损坏磁盘时

很有价值。

        除了客户端读取时会检验block之外,每一个datanode运行一个DataBlockScanner,它会周期性检查

datanode中所存储的所有block。这样做是为了防止物理存储媒介的位衰减。

        由于HDFS存储了block的副本,它可以通过拷贝好的副本来“恢复”损坏的block。它的工作方式是如果

客户端读取block时发现一个错误,再抛出一个ChecksumException之前,它会把试图从namenode读取的

block和datanode报告给namenode,namenode标记这个block为损坏的,这样它不会再把客户端定位到

它或把它拷贝到别的datanode。然后它从其它的datanode上拷贝一个副本,这样复制因子回复到期望水平。

一旦复制完毕,删除损坏的副本。

        在使用FileSystem的open()方法之前,可以通过传递false给setVerifyChecksum()方法来禁止检验和检查。

在shell中,在使用-get或-copyToLocal命令时,同样可以通过使用-ignoreCrc选项来达到同样的效果。这个

特性在你想要检查损坏文件来决定如何处理它是有用。例如,你可能希望在删除之前查看它是否还能恢复。

        你可以使用hadoop fs -checksum来查看一个文件的校验和。这在查看HDFS中的两个文件内容是否一样

时很有用----例如,distcp会做这些事。


LocalFileSystem

        HADOOP 的LocalFileSystem执行客户端的校验。这意味着当你写一个名叫filename的文件,客户端文件系统

会创建一个文件,filename.crc,与包含文件每一块的校验和同一个目录。块的大小由file.bytes-per-checksum属性

控制,默认值是512byte。块的大小做为.crc文件的一个元数据保存在.crc文件中,所以如果改变了块的大小,这个

文件还是可以正确读取。当读取文件时,会检查校验和,如果有错误,LocalFileSystem会抛出一个ChecksumException。

        计算校验和耗费很少(在JAVA中,他们是用native代码实现),读写文件时一般会增加百分之几的耗时。对于

大部分应用,为了确保数据完整性这个代价是可以接受的。也可以禁止校验和验证,这样做一般是底层文件系统本身

支持校验和检查。可以使用RawLocalFileSystem代替LocalFileSystem来完成。为了在整个应用中达到这个目的,可以

重新映射file URI的实现,设置fs.file.impl的属性值为org.apache.hadoop.fs.RawLocalFileSystem。或者,你可以直接

创建一个RawLocalFileSystem实例,在你只想禁止校验某些读取时有用,例如:

Configuration conf = ...
FileSystem fs = new RawLocalFileSystem();
fs.initialize(null, conf);


ChecksumFileSystem

         LocalFileSystem使用ChecksumFileSystem做它的工作,这个类给其它不支持校验和的文件系统添加校验和功能很容易,

因为ChecksumFileSystem只是FileSystem的一个包装。一般程式如下:

FileSystem rawFs = ...
FileSystem checksummedFs = new ChecksumFileSystem(rawFs);
        底层的文件系统叫raw文件系统,可以通过ChecksumFileSystem的getRawFileSystem()方法得到。ChecksumFileSystem

有几个更有用的方法,如用来得到任意文件的校验和文件的方法getChecksumFile()。

        当ChecksumFileSystem读取文件时发现一个错误,它会调用它的reportChecksumFailure()方法。默认的实现不做任何事,

但LocalFileSystem会把损坏文件及它的校验和移动到同一个设备上的bad_files文件夹。管理员应该周期性检查这些文件并

对它采取行动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值