java.io.IOException:org.apache.hadoop.fs.ChecksumException: Checksum error 校验和(checksum)出现异常

在查询hive中的数据时,报如下错误:

错误原因:

从提示用可以看出是:CheckSumException ,即 校验和异常,出现该错误的原因:存储的数据与hadoop系统为该数据生成的校核和数据不一致导致错误,说白了,就是你存储的数据出现问题了,如:人为手动更改了数据,网络不稳定以及硬件损坏等因素导致的。本博客是我自己为了复现这个错误,特地更改了hive上的源数据。

如上图,我是通过notepad++更改了源数据,不是通过hive命令更改了数据,导致crc文件并没有做相应的更新,当我再次在hive使用select查询语句查询源数据的时候,就报了校验和异常。说明源数据遭到了损坏。此时,为了能查询到数据,直接将crc文件删除,再使用select查询语句即可查询到响应的数据。

为了详细了解hadoop的校验原理,参考下面的博客:

博客链接:https://blog.csdn.net/lb812913059/article/details/79718303

博客标题:Hadoop数据完整性与CheckSum校验原理

博客原文:

一、HDFS数据完整性
用户肯定都希望系统在存储和处理数据时,数据不会有任何丢失或损坏。但是,受网络不稳定、硬件损坏等因素,IO操作过程中难免会出现数据丢失或脏数据,难免会出现数据丢失或脏数据,数据传输的量越大,出现错误的概率就越高。

检测数据是否损坏的常见措施是,在数据第一次引入系统时计算校验和(checksum)并存储,在数据进行传输后再次计算校验和进行对比,如果计算所得的新校验和和原来的校验和不匹配,就认为数据已损坏。但该技术并不能修复数据——它只能检测出数据错误。(这正是不使用低端硬件的原因。具体说来,一定要使用ECC内存。)注意,校验和也是可能损坏的,不只是数据,但由于校验和比数据小得多,所以损坏的可能性非常小。

(1)对本地文件I/O的检查
在Hadoop中,本地文件系统的数据完整性由客户端负责。重点在于存车读取文件时进行校验和的处理。
具体做法是:每当hadoop创建文件a时,hadoop就会同时在同一个文件夹下创建隐藏文件.a.crc,这个文件记录了 文件a的校验和。针对数据文件的大小,每512个字节会生成一个32位的校验和(4字节),可以在src/core/core-default.xml中通过修改io.bytes.per.checksum的大小来修改每个校验和所针对的文件的大小。

在hadoop中,校验和系统单独为一类,org.apache.hadoop.fs.ChecksumFileSystem,当需要校验和机制时,可以很方便的调用它来服务。

(2)对HDFS的I/O数据进行检查

一般来说,HDFS会在三种情况下检验校验和:

DataNode接收数据后存储数据前
DataNode接收数据一般有两种情况:1.从客户端上传数据 2.DataNode从其他DataNode上接收数据。
当客户端上传数据时,正在写数据的客户端将数据及其校验和发送到由一系列datanode组成的Pipeline管线。Pipeline管线中最后一个datanode负责验证校验和。

DataNode数据存储步骤:(包括从DataNode和客户端两种传输方式)
1.在传输数据的最开始阶段,Hadoop会简单地检查数据块的完整性信息;
2.依次向各个DataNode传输数据,包括数据头信息、块信息、备份个数、校验和等;
3.Hadoop不会在数据每流动到一个DataNode都检查校验和,只会在数据流达到最后一个节点时才检查校验和
如果在验证过程中发现有不一致的块,就会抛出CheckSumException异常信息

客户端读取DataNode上的数据时
Hadoop会在客户端读取DataNode上的数据时,使用DFSClient中的read函数先将数据读入到用户的数据缓冲区,然后再检查校验和。将他们与datanode中存储的校验和进行比较
每个datanode均持久保存有一个用于验证的校验和日志,所以它知道每个数据块的最后一次验证时间
客户端成功验证一个数据块后,会告诉这个datanode,datanode由此更新日志

DataNode后台守护进程的定期检查
DataNode会在后台运行DataBlockScanner,这个程序定期验证存储在这个datanode上的所有数据块(3周)
该项措施是解决物理存储媒体上位衰减,位损坏的有力措施。

Hadoop处理损坏数据的机制:

DataNode在读取block块的时候会先进行checksum(数据块校验和)
如果client发现本次计算的校验和跟创建时的校验和不一致,则认为该block块已损坏
客户端在抛出ChecksumException之前上报该block信息给namenode进行标记(“已损坏”)
这样namenode就不会把客户端指向这个block,也不会复制这个block到其他的datanode。
client重新读取另外的datanode上的block
在心跳返回时NameNode将块的复制任务交给DataNode,从完好的block副本进行复制以达到默认的备份数3
NameNode删除掉坏的block。
DataNode在一个block块被创建之日起三周后开始进行校验
如果出于一些原因在操作的时候不想让hdfs检查校验码:

在FileSystem的open()之前通过设置FileSystem的setVerifyCheckSum(false)方法禁用校验和
或者命令行使用get时候添加选项-ignoreCrc或者直接使用-copyToLocal
    fs.setVerifyChecksum(false)   fs.open(new Path(“”)) // 就不进行校验检查了
    Hadoop fs –get –ignoreCrc hdfs://master:9000/a.txt
    Hadoop fs –copyToLocal hdfs://master:9000/a.txt


二、CheckSum校验原理
Hadoop数据的完整性检测,都是通过校验和的比较来完成,在创建新文件时(也就是在上传数据到hdfs上时)将校验和的值和数据一起保存起来。NameNode会收到来自client、DataNode的检验和信息,根据这两个信息来维护文件的块存储及向客户端提供块读取服务。

HDFS会对写入的所有数据计算校验和,并在读取数据时验证校验和。
常用的错误检测码是CRC-32(循环冗余校验),任何大小的数据输入均计算得到一个32位的整数校验和。
在写入文件时,hdfs为每个数据块都生成一个crc文件。客户端读取数据时生成一个crc与数据节点存储的crc做比对,如果不匹配则说明数据已经损坏了。数据节点在后台运行一个程序定期(默认为21天)检测数据,防止物理存储介质中位衰减而造成的数据损坏。

1 DataNode在写入时计算出校验和,然后每次读的时候再计算校验和进行检验
hdfs会为每一个固定长度的数据(一个个数据包)执行一次校验和
这个值由io.bytes.per.checksum指定,默认是512字节。
因为CRC32是32位即4个字节,这样校验和占用的空间就会少于原数据的1%。

2  datanode在存储收到的数据前会校验数据的校验和,比如收到客户端的数据或者其他副本传过来的数据。
如hdfs数据流中客户端写入数据到hdfs时的数据流,在管道的最后一个datanode会去检查这个校验和
如果发现错误,就会抛出ChecksumException到客户端

3 从datanode读数据的时候一样要检查校验和,而且每个datanode还保存了检查校验和的日志,每次校验都会记录到日志中

除了读写操作会检查校验和以外,datanode还跑着一个后台进程(DataBlockScanner)
定期校验存在在它上面的block,因为除了读写过程中会产生数据错误以外,硬件本身也会产生数据错误,比如位衰减(bit rot)
 

三、CheckSum产生的性能问题以及既然有性能问题,为什么还要进行校验和?

hdfs都是存储大文件的,每512字节就做一个crc校验,客户端在读写文件都要做这个校验,这个对hdfs的性能消耗是比较大的,crc最开始是采用jni调用,但是jni调用都要做上下文切换,加上每512字节就做一次crc校验,所以导致jvm切换很频繁,后来修改为pure java的crc校验,性能还提高了下,如果是几百兆就做一个crc校验,那么jni调用导致的上下文切换少些,那么jni就还有优势,但是在hadoop这个应用场景明显不合适。

后来淘宝的针对hadoop的crc场景,定制了jvm,将crc指令优化为调用硬件指令,性能测试报告证明提高了hdfs性能的20%-30%

hadoop为什么要设计crc校验

既然crc校验对hdfs有这么大的性能损耗,那么hadoop还为什么要用crc校验呢,hadoop设计的应用场景就是离线数据的分布式计算,所以这些数据会保存很久,保存一个月,半年,一年,十年等。而数据保存这么久,那么物理存储介质由于中位衰减,会造成数据损坏,这对一个大文件来说,很容易导致一个块由于时间关系,硬盘错位,最终导致整个文件都是错误的,这对离线处理来说是不可以接受的,所以我想,hadoop就是为了离线处理的应用场景,才设计出crc校验。如果hadoop是做实时处理的,crc校验就没有必要了,毕竟数据不会放多久。

参考:https://blog.csdn.net/lskyne/article/details/8929235

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值