前言
本文主要介绍hdfs 流式接口中数据块的传输格式。BlockSender类主要负责从数据节点的磁盘目录读取数据块文件,然后发送给数据接收方。发送的数据是有一定结构格式的。
数据传输格式
如图所示,packetlength大小一般为CHECKSUMS校验数据大小 + DATA真实数据大小。
传输格式解析
下面详细解析这个数据格式,BlockSender发送数据的格式包含两个部分:校验信息头(ChecksumHeader)和数据包序列(packets):
校验信息头(ChecksumHeader) | 数据包序列(packets) |
A. ChecksumHeader:
ChecksumHeader是一个校验信息头,用于描述当前datanode使用的校验方式等信息,一个校验信息头的结构也包含两个部分:
1 byte 校验类型(CHECKSUM_TYPE) | 4 byte 校验块大小(BYTES_PER_CHECKSUM)
数据校验类型:数据校验类型定义在org.apache.hadoop.util.DataChecksum中,目前包括三种校验方式----空校验、CRC32以及CRC32C。这里使用1byte描述校验类型,分别对应于值0、1、2、
校验块大小:校验信息头中的第二个部分是校验块大小,也就是多少字节的数据产生一个校验值。这里以CRC32为例,一般情况下是512字节的数据产生一个4字节的效验和,我们把512字节的数据成为一个校验块(chunk),它是hdfs中读取和写入数据块操作的最小单元。
B. 数据包序列
BlockSender会将数据切分成若干个数据包( packet)对外发送,当数据发送完成后,会以一个空的数据包作为结束。每个数据包都包括一个变长的包头、校验数据以及若干个字节的实际数据:
变长的数据包头(packetHeader) |
校验数据 |
实际数据........---------------- |
数据包头:用于描述当前数据包的信息,是通过Protobuf序列化的,包括4字节的全包长度,以及2字节的包头长度,之后紧跟如下数据包信息:当前数据包在整个数据块中的位置;数据包在管道中的序列号;当前数据包是不是数据块中的最后一个数据包;当前数据包中数据部分的长度;是否需要DN同步。
校验数据:校验数据是对实际数据做校验操作产生的,它将数据数据以校验块为单位,每个校验块产生一个效验和,校验数据中包含了所有校验块的效验和。
实际数据:数据包中的实际数据就是数据块文件中保存的数据,实际数据的传输是以校验块为单位的,一个校验块对应产生一个校验和的实际数据。在数据包中会将校验块与校验数据分开发送,首先将所有校验块的校验数据发送出去,然后再发送所有的校验块。