目录

客户端读

getLocatedBlocks(String src, long start, long length)

DFSInputStream.read(byte[] buffer, int offset, int length)

客户端写

写流程

Packet(DFSPacket)的构成

DataStream与Datanode交互


客户端读

hdfs客户端读会先调用open方法,open会调用先getBlockLocations来获取块信息,
然后通过openinternal生成DFSInputStream对象,通过DFSInputStream读数据。

getLocatedBlocks(String src, long start, long length)

客户端会调用getLocatedBlocks()方法获取HDFS文件指定范围内所有数据块的位置信息。这个方法的参数是HDFS文件的文件名,起始偏移和长度,返回值是文件指定范围内所有数据块的文件名以及他们的位置信息,使用LocatedBlocks对象封装。(length似乎没有用,默认都是传的128M,返回都是所有的块信息)

Proto_namenode:

rpc getBlockLocations(GetBlockLocationsRequestProto)

      returns(GetBlockLocationsResponseProto);

LocateBlocks数据结构:

hdfs源代码下载_客户端

DFSInputStream.read(byte[] buffer, int offset, int length)

在read方法中首先使用blockSeekTo方法定位到所要读取dn上,然后使用readBuffer方法获取数据。

hdfs源代码下载_hdfs源代码下载_02

blockSeekTo方法会根据LocateBlocks列表以及读的位置选择block最优的的dn(即LocateBlock对象),根据LocateBlock中locs的host:port创建socket,最后生成对应的BlockReader。HDFS有两种BlockReader,分别是BlockReaderLocal和BlockReadRemote。以下BlockReadRemote为例。

BlockReadRemote创建的时候,首先会向socket中发送一个readBlock命令。命令由三部分组成DataTransferProtocol.DATA_TRANSFER_VERSION(short,=28),opcode(1byte,read_block=81)和OpReadBlockProto(通过proto.writeDelimitedTo写入)。Dn接到请求以后,返回一个BlockOpResponseProto(通过proto.writeDelimitedTo写入)。Check返回status为ok才完成reader的初始化。

readBuffer方法主要用于读取数据,本质上其实就是BlockReadRemote.read方法。read中会调用readNextPacket方法,此方法的逻辑是会向server端不停的获取数据包,获取数据完全后,会向server端再获取一个空包,空包上会有LastPackctInBlock的标记,验证标记后,会向server端写入一个ClientReadStatusProto。

PacketReceiver.recevieNextPacket方法中记录了包的结构如下:

hdfs源代码下载_hdfs源代码下载_03

客户端写

在分析写数据之前,首先要理解hdfs中的block、packet、chunk。

Block

每个hdfs上的文件都是由元数据(描述数据的数据),数据块组成,而block就是数据块的意思。Hdfs上的数据块大小一般是128MB。Block都存储在Datanode上面。

Packet

Hdfs客户端与Datanode之间使用Packet来传输数据,默认大小64MB。

Chunk

组成Packet中数据的最小单位。每个chunk主要由512Byte数据和4Byte校验位组成,总长度为516Byte,64MB大小Packet能包含的126个Chunk。校验位通过CRC32算法生成。

写流程

hdfs源代码下载_hadoop_04

DFSClient.create会调用DFSOutputStream.newStreamForCreate方法,此方法会向Namenode发送create请求(rpc create(CreateRequestProto)returns(CreateResponseProto))。请求完成后会创建一个DataStreamer,Datastreamer会和Datanode做数据交互。DFSOutputStream在写数据会把数据先变成一个一个chunk,然后多个chunk会组成一个packet,然后会交给DataStreamer的发送队列。DataStreamer在发送数据之前会查看有没有block,如果没有会调用DFSOutStream.addBlock先增加一个block(rpc addBlock(AddBlockRequestProto) returns(AddBlockResponseProto)),然后发送packet。

Packet(DFSPacket)的构成

hdfs源代码下载_客户端_05

DataStream与Datanode交互

hdfs源代码下载_hadoop_06