DFSClient中的读Block机制

BlockReader是InputStream的一个具有校验功能的warper,用于与DataNode交互,传递块数据。

BlockReader中的readChunk用于从DataNode中读取块信息和块数据(chunk=block);read方法如果发现块数据校验码无误,就向DataNode发送OP_STATUS_CHECKSUM_OK表示无错误发生。

DFSInputStream是DFSClient用于读取文件块的方法,其内包含了blockReader用于与DataNode交互(在readBuffer中调用BlockReader的read方法读取块内容)。

在读取文件块时,采用预读取方式,根据访问局部性原理,从offset开始(offset初始为0,即文件头),将长度为prefetchSize的块集合信息读到localBlocks(这是一个LocalBlock列表,可以视为缓存。LocalBlock是由{Block,DatanodeInfo[]}构成的pair,用于定位块,继承于Writeable)中,即

callGetBlockLocations(namenode, src, offset, prefetchSize);

如果读取的内容不在localBlocks中,就从namenode中读取offset开始,长度为prefetchSize的块,并加入到localBlocks缓存中。

LocalBlock与BlockReader的关系:LocalBlock用于定位Block,而BlockReader用于读取该Block的内容。

当需要读取一个Block时

public synchronized int read(byte buf[], int off, int len)

先调用blockSeekTo获取块所在的datanode建立连接并根据localBlock获取相应的BlockReader(内部流程:

根据offset获取LocalBlock-->调用chooseDatanode获取块所在的DataNode-->与datanode建立连接;调用localBlock的getBlock()获取block,根据这个block创建一个BlockReader)-->调用readBuffer,用blockReader的read读取block(注:BlockReader的read在每次读取时都会调用checksumOk对block进行校验)

当需要读取多个块

int read(long position, byte[] buffer, int offset, int length)

(注:position为要读取的文件开始位置,offset是从buffer的offset位置开始存)时,首先调用getBlockRange获取length范围内的所有块的LocalBlock,再对于每个LocalBlock依次调用fetchBlockByteRange读取相应的块到buffer中(执行流程是先根据LocalBlock生成一个BlockReader对象,在调用这个reader的readerAll方法读取块到buffer中)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/c95695af7e7f611a06011bb817490558.html