阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

HDFS Append时packet的格式以及DataNode对block/checksum文件的处理

218次阅读
没有评论

共计 3271 个字符,预计需要花费 9 分钟才能阅读完成。

HDFS Append 时 packet 的格式以及 DataNode 对 block/checksum 文件的处理

HDFS 的 Block 一般比较大,默认 64MB/128MB,客户端给 DataNode 发数据实际上是以 Packet 的形式发送的,Packet 一般只有 64KB 左右。Packet 内部由分为一个个 chunk,每个 chunk 一般情况 (后面会说非一般情况) 下 512Bytes,并且 Packet 内部对于每个 chunk 会带上这个 chunk 的 checksum,对于 CRC 来说,checksum 本身占用 4Bytes。一个 Packet 的结构如下:
HDFS Append 时 packet 的格式以及 DataNode 对 block/checksum 文件的处理

其中 header 中包含了一些元信息,比如这个 packet 是不是所属 block 的最后一个 packet,数据长度多少,编码多少,packet 的数据部分的第一个字节在 block 中的 offset,DataNode 接到这个 Packet 是否必须 sync 磁盘。

下面主要关注当客户端使用如下模式写数据时,数据是怎样被封装成一个个 packet 的:

FSDataOutputStream out = fs.append(new Path(file));
out.write(b, off, len);
out.hflush()

首先,假设需要进行 append 的 file 一开始不存在,没有任何数据。
实际上,out 是 HdfsDataOutputStream 类型,out.write(b,off,len)最终调用了 HdfsDataOutputStream 包含的 DFSOutputStream 类型对象,转而调用的是 DFSOutputStream 的父类 FSOutputSummer 的 write(b,off,len),FSOutputSummer 从名字可以看出,对数据进行了 checksum.

FSOutputSummer 的 write(b,off,len)实质上就一行:

for (int n=0;n<len;n+=write1(b, off+n, len-n)) {}

实际上就是循环的调用 write1 方法将数据写入,write1 方法会去检查是否写入的数据满了一个 chunk(正常情况下 512Bytes),如果满了,则为这个 chunk 计算一个 checksum,4 个字节,然后将这个 chunk 和对应的 checksum 写入当前 Packet 中(DFSOutputStream 的 writeChunk 方法),格式就是上面那个图中的格式。当 Packet 满了,也就是说塞入的 chunk 的个数到达了预先计算的值,就将这个 packet 放入 dataQueue,后台会有一个 DataStreamer 线程专门从这个 dataQueue 中取一个个的 packet 发送出去。

到这里,都比较清晰,需要注意的是,如果 append 的 file 中本身已经存在了一些数据,比如 512+512+100Bytes,那么在调用 out.write(b,off,len)向 file 中追加新的数据时,构造的第一个 packet 中只有一个 chunk,并且这个 chunk 的大小是 512-100=412Bytes,这个 packet 之后的 packet 的 chunk 是标准 512Bytes。

if (appendChunk && bytesCurBlock%bytesPerChecksum == 0) {appendChunk = false;
        // 下次计算 checksum 时的 chunk 大小是512Bytes,不再是412Bytes
        resetChecksumChunk(bytesPerChecksum);
}
      

以上代码来自 DFSOutputStream 的 writeChunk 方法,其中 appendChunk 在 fs.append 时会被置为 true,并且 bytesCurBlock 会初始化为 append 之前文件的大小,当构造完特殊包后,bytesCurBlock 增加了 412Bytes,将上次的 paritial chunk 补齐了。

DataStreamer 从 dataQueue 中取 packet 发送出去的过程不关注,下面看 DataNode 针对 append 如何处理 block 文件和 block 的 checksum 文件。

DataNode 上接受 Block 的逻辑封装在 BlockReceiver 中,其中,receiveBlock 方法中有一段代码

while (receivePacket() >= 0) {/* Receive until the last packet */ }

每调一次 receivePacket,DataNode 就接收一个 packet,将 packet 的 data 和 checksum 都拿出来,进行一次校验,看数据在发送过程中是否损坏,然后看 block 在当前 DataNode 上的副本在磁盘上的长度是否是 chunk 的整数倍,如果不是,则将 block checksum 文件 (blk_1100893627_27540491.meta) 的输出流 seek 到最后一个 checksum,并且将最后一个 checksum 读出来,如下代码:

 if (onDiskLen % bytesPerChecksum != 0) {// prepare to overwrite last checksum
            adjustCrcFilePosition();
 }
          
 // If this is a partial chunk, then read in pre-existing checksum
 if (firstByteInBlock % bytesPerChecksum != 0) {LOG.info("Packet starts at" + firstByteInBlock +
                     "for" + block +
                     "which is not a multiple of bytesPerChecksum" +
                     bytesPerChecksum);
   long offsetInChecksum = BlockMetadataHeader.getHeaderSize() +
                onDiskLen / bytesPerChecksum * checksumSize;
   computePartialChunkCrc(onDiskLen, offsetInChecksum, bytesPerChecksum);
 }

然后将数据写入 block 文件(blk_1100893627), 将 checksum 写入 block checksum 文件(blk_1100893627_27540491.meta)

block file 和 block checksum file 格式如下:

HDFS Append 时 packet 的格式以及 DataNode 对 block/checksum 文件的处理
HDFS Append 时 packet 的格式以及 DataNode 对 block/checksum 文件的处理

参考资料

Hadoop 2.5.0

Hadoop 如何修改 HDFS 文件存储块大小  http://www.linuxidc.com/Linux/2013-09/90100.htm

Hadoop 中 HDFS 的存储机制  http://www.linuxidc.com/Linux/2014-12/110512.htm

将本地文件拷到 HDFS 中 http://www.linuxidc.com/Linux/2013-05/83866.htm

从 HDFS 下载文件到本地 http://www.linuxidc.com/Linux/2012-11/74214.htm

将本地文件上传至 HDFS http://www.linuxidc.com/Linux/2012-11/74213.htm

HDFS 基本文件常用命令 http://www.linuxidc.com/Linux/2013-09/89658.htm

Hadoop 中 HDFS 和 MapReduce 节点基本简介 http://www.linuxidc.com/Linux/2013-09/89653.htm

《Hadoop 实战》中文版 + 英文文字版 + 源码【PDF】http://www.linuxidc.com/Linux/2012-10/71901.htm

更多 Hadoop 相关信息见Hadoop 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=13

本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-03/115176.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计3271字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中