您的位置:首页 > 运维架构

hadoop深入研究:(六)——HDFS数据完整性

2013-06-24 11:52 197 查看
转载请注明出处:hadoop深入研究:(六)——HDFS数据完整性

数据完整性

IO操作过程中难免会出现数据丢失或脏数据,数据传输得量越大出错得几率越高。校验错误最常用得办法就是传输前计算一个校验和,传输后计算一个校验和,两个校验和如果不相同就说明数据存在错误,比较常用得错误校验码是CRC32.

hdfs数据完整性

hdfs写入的时候计算出校验和,然后每次读的时候再计算校验和。要注意的一点是,hdfs每固定长度就会计算一次校验和,这个值由io.bytes.per.checksum指定,默认是512字节。因为CRC32是32位即4个字节,这样校验和占用的空间就会少于原数据的1%。1%这个数字在hadoop中会经常看到。以后有时间会整理一份hadoop和1%不得不说的故事。 datanode在存储收到的数据前会校验数据的校验和,比如收到客户端的数据或者其他副本传过来的数据。想一下前面的文章hadoop深入研究:(三)——hdfs数据流中客户端写入数据到hdfs时的数据流,在管道的最后一个datanode会去检查这个校验和,如果发现错误,就会抛出ChecksumException到客户端。 客户端从datanode读数据的时候一样要检查校验和,而且每个datanode还保存了检查校验和的日志,客户端的每一次校验都会记录到日志中。 除了读写操作会检查校验和以外,datanode还跑着一个后台进程(DataBlockScanner)来定期校验存在在它上面的block,因为除了读写过程中会产生数据错误以外,硬件本身也会产生数据错误,比如说位衰减(bit rot)。 如果客户端发现有block坏掉呢,会怎么恢复这个坏的块,主要分几步: 1.客户端在抛出ChecksumException之前会把坏的block和block所在的datanode报告给namenode 2.namenode把这个block标记为已损坏,这样namenode就不会把客户端指向这个block,也不会复制这个block到其他的datanode。 3.namenode会把一个好的block复制到另外一个datanode 4.namenode把坏的block删除掉 如果出于一些原因在操作的时候不想让hdfs检查校验码,在调用FileSystem的open方法前调用setVerityCheckSum方法,并设为为false即可,命令行下可以使用-ignoreCrc参数。

实现

LocalFileSystem继承自ChecksumFileSystem,已经实现了checksum功能,checksum的信息存储在与文件名同名的crc文件中,发现错误的文件放在bad_files文件夹中。如果你确认顶层系统已经实现了checksum功能,那么你就没必要使用LocalFileSystem,改为用RowLocalFileSystem。可以通过更改fs.file.impl=org.apache.hadoop.fs.RawLoacalFileSystem全局指定,也可以通过代码直接实例化。
Configuration conf=...
        FileSystem fs=new RawLocalFileSystem();
        fs.initialize(null, conf);
如果其他的FileSystem想拥有checksum功能的话,只需要用ChecksumFileSystem包装一层即可:
FileSystem rawFs=...
        FileSystem checksummedFs=new ChecksumFileSystem(fs){} ;


感谢Tom White,此文章大部分来自于大神的definitive guide,奈何中文版翻译太烂,就在英文原版的基础上和官方的一些文档加入一些自己的理解。全当是读书笔记吧,画蛇添足之举。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: