Hbase如何写入hdfs

介绍

这篇文章给大家分享的是有关Hbase如何写入hdfs的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

下图是描述Hbase底层存储结构的顶层结构图。可以看到Hbase将处理HFile文件(memstore生成)和HLog文件(细胞膜生成)这两种文件都将有HRegionServer管理,当真正存储到hdfs中时,会使用DFS客户作为hdfs的客户端把大批量的这两种数据流写到多个DataNode节点中。
 Hbase如何写入hdfs

之前在细胞膜线程模型源码分析中为了突出重点说明细胞膜线程模型,并未具体说明writer.append()和writer.sync()中作家实例是什么,在FSHLog中被反复无常的关键字修饰声明为一个WALProvider。作家类型的接口:
 Hbase如何写入hdfs”> <br/> <img src=

在这里我们仅仅讨论使用hdfs作为Hbase的文件系统,也即是init参数中fs(系统)是DistributedFileSystem的实例。在其createNonRecursive的实现的参数除了路径参数指明需要在hdfs创建的文件路径比较重要以外,还有一个复制参数也很重要,这个参数说明了备份数量也即是写datanode份数.DistributedFileSystem中dfs是DFSClient的实例引用,也即最开始那张架构图中所指的dfs Client.hbase使用DFSClient的制造方法通过RPC调用向hdfs的namenode创建一个文件并构造了输出流DFSOutputStream实例,这个方法另外一个重点就启动了一个管道,具体调用是streamer.start(),这个流水线是Hbase向hdfs的多个datanode管道写的实现,虽然这里分析的是细胞膜的写入过程,但是其实keyvalue写到memstore,再写到HFile后也是采用这种方式管道写(管道)的方式实现。

 Hbase如何写入hdfs”> <br/> <img src=

通过RPC调用namenode的创建函数,调用namesystem。startFile函数,其又调用startFileInternal函数,它创建一个新的文件,状态为under construction,没有任何data block与之对应。于此同时创建成功后会返回一个DFSOutputStream类型的实例,在FSDataOutputStream中被称作wrappedStream,该对象负责处理datanode和namenode之间的通讯。

Hbase如何写入hdfs

hdfs的文件结构,HDFS一个文件由多个block(默认64MB)构成。这里通过注释可以看到HDFS在进行block读写的时候是以packet(默认每个packet为64K)为单位进行的。每一个packet由若干个chunk(默认512Byte)组成。Chunk是进行数据校验的基本单位,对每一个chunk生成一个校验和(默认4Byte)并将校验和进行存储。

分析到这,已经可以看出hbase文件写入hdfs的过程并没有特别,hdfs就把hbase当做hdfs的client然后封装成chunk再组装成packet,再向datanode批量写数据。为了保证数据有序的传输,使用了数据发送队列dataqueue和待确认队列ackqueue,并使用两个线程DFSOutputStream$DataStreamer和DFSOutputStream$DataStreamer$ResponseProcessor(在run()中)分别来发送数据到对应block和确认数据是否到达。

还有另外一个重点就是hbase是如何把数据到datanode的磁盘的。

在此,我们又要回到ProtobufLogWriter类中因为writer.sync()最终调用的就是ProtobufLogWriter的writer方法,它的源码如下:
Hbase如何写入hdfs

就像注释中所解释的一样,hflush是同步的只能保证能让新reader能看到,但是并不能保证其真正的持久化到了每个datanode中,也即没真的调用posix中的fsync()系统调用。它只是将client端写入的数据刷到每个DataNode的OS缓存(store)中,如果每个副本所在的DataNode同时crash时(例如机房断电)将会导致数据丢失。

hdfs给客户端还提供了另外一种语义hsync:client端所有的数据都发送到副本的每个datanode上,并且datanode上的每个副本都完成了posix中fsync的调用,也就是说操作系统已经把数据刷到磁盘上(当然磁盘也可能缓冲数据);需要注意的是当调用fsync时只有当前的block会刷到磁盘中,要想每个block都刷到磁盘,必须在创建流时传入Sync标示。

hbase当前选择的是hflush语义。这两种语义都调用的flushOrsync方法,其中hflush调用的isSync传入false,而hsync传入的是true。

Hbase如何写入hdfs