hdfs学习笔记
1. dfsclient
packet的大小,65557,一个packet有127个chunk,一个chunk有512字节,他的checksum为4个字节,
写入的时候,每512个字节调用一次加入到packet(最后一个可以不满512字节,close或者flush的时候)
每个block有多个packet, 默认64M
客户端发送读取请求在DFSClient的newBlockReader中
?调用namenode增加一个新的块
public abstract void org.apache.hadoop.hdfs.protocol.ClientProtocol.create
?
inode体系是用loadfsimage中来的,也可能中途增加再写入回去。
?3.datanodeResponseProcessor会处理ack队列,BlockReceiver的verifyChunks会校验chekcsum
?
向本地磁盘写入数据和向另外一个datanode发送数据都在BlockReceiver的receivePacket()中,先向datanode发送数据,然后本地再校验checksum和写入数据到磁盘,退出这个方法后,再向datanode写一个0,表示传送完成。
?
每次写入数据到磁盘(一次receive后,都会向PacketResponder的ackQueue入队一个ack消息,然后另外一个线程取出来,并且如果不是最后一个datanode,就等待后面的datanode的ack。然后再看是否这个block全部搞完了,搞完了就通知下namenode,在发送ack到前面一个datanode或者客户端)?
?
3.1? 在blockReceiver.receiveBlock在blockReceiver.receiveBlock方法中,主要完成两件事情
?a.启动一个PacketResponder
?b.receivePacket
?????? a.将消息转发给下一台
?????? b.写入文件到临时文件
?????? c.向PacketResponder的队列加入一个消息
?
PacketResponder从队列取本地或者下一台的返回(本地的直接从队列取出,下一台的从mirrorIn中取出)
lastPacketInBlock的判断方式是:
boolean lastPacketInBlock = (buf.get() != 0); (看下包的协议是怎么规定的)
?
当发现是最后一个packet的时候,调用:
datanode.data.finalizeBlock(block);
这里会将临时目录的文件移动到current目录,并删除临时目录的文件.
?
writer.syncFs();是刷新数据到服务器的临时目录上
writer.close();是让服务器完成finalizeBlock的动作,然后才可以查询到。
这里先写临时目录,很大一个原因是这样拷贝一次后,新的快将是一个连续的磁盘快,提高后来读取的效率。
?
事实上,hbse的每次hlog的写入,都是writer.syncFs();写入到服务器上去了的。然后在日志滚动等的时候调用writer.close()正式完成写入。当然,如果写入的log大小超过了一个块,也会写到服务器上并可以查询的。因为上面的分析中,是lastpacket(of a block)的时候从临时变为正式。但这些快都是一个文件的,只有rollLog后才会有新的文件.
?
inode体系没有datanode的信息,在FSNameSystem.getBlockLocationsInternal中(读取文件的块信息),从FSNameSystem的blocksMap中取出来的。放在DatanodeDescriptor中,再把DatanodeDescriptor各个放到machineSet,最后和block一起创建LocatedBlock,把所有的快放到LocatedBlocks中,再通过clusterMap排序后返回.