HDFS的hflush,hsync和close有啥区别,分别做了什么
hflush: 语义是保证flush的数据被新的reader读到,但是不保证数据被datanode持久化.
hsync: 与hflush几乎一样,不同的是hsync保证数据被datanode持久化。
close: 关闭文件.除了做到以上2点,还保证文件的所有block处于completed状态,并且将文件置为closed
场景是写一个字节(append或者create),然后调用hflush.看看hflush做了什么。
涉及到几个线程,一个是调FSDataOutputStream的write的线程,它是应用程序自己的线程,write会将数据以packet的形式一个个的丢入data queue中。
另外两个是HDFS客户端代码中的线程,其中一个是DataStreamer,负责从data queue中取出一个个的packet发出去,过程是为每个block建立一个pipeline,然后发packet,最后关闭pipeline,接着下一个block。另外一个是ResponseProcessor,负责处理下游节点的ack。
实际上,packet是由chunk组成的,每个chunk对应一个checksum,一个packet大概64KB左右,一个chunk通常512字节。通常情况下,每512字节算一个checksum,写入到packet中。但是最后一个chunk通常是不满512字节。hflush实际上,就是将最后不满一个chunk的数据算checksum,然后
写入packet,最后将这个packet放入data queue队列.在我们只写一个字节的场景下,一个字节不够一个chunk,故data queue中始终每个packet,DataStreamer始终等待着没有建立pipeline,调用hflush后,往data queue塞入一个packet,DataStreamer终于从data queue中取到一个packet,然后建立pipeline,接着发送packet。调完hflush的应用程序线程一直在等待最后一个packet的ack被收到,轮到ResponseProcessor上场。他不断的处理从datanode收到的packet ack,不断更新block的长度。接着,执行hflush的应用程序线程终于等到了最后一个packet的ack,然后它告诉namenode最后一个block的长度,namenode更新内存状态,实际
上是根据文件名找到INodeFile,将block长度写入,并且记一条edit log.
下面看看关闭文件close时做了什么.
FSDataOutputStream的close:
一开始也是和hflush一样,将最后一个packet进data queue,不同的是还会生成一个特殊的packet入data queue,lastPacketInBlock标记设为true,意思是告诉datanode这是block的最后一个packet,然后等最后这个包的ack收到。接着关闭DataStreamer和ResponseProcessor线程。然后调用completeFile(),最后结束file lease.
看看completeFile():
通知namenode,namenode会做一些检查:
最后看看hsync.
实现上和hflush几乎一样,代码共有,特殊的是最后一个packet标记为syncBlock状态,datanode收到后就会落盘了.
hadoop-hdfs-2.4.1.jar