`
085567
  • 浏览: 214053 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

HFile存储格式

阅读更多

HBase中的所有数据文件都存储在Hadoop HDFS文件系统上,主要包括两种文件类型:

1. HFile, HBase中KeyValue数据的存储格式,HFile是Hadoop的二进制格式文件,实际上StoreFile就是对HFile做了轻量级包装,即StoreFile底层就是HFile

2. HLog File,HBase中WAL(Write Ahead Log) 的存储格式,物理上是Hadoop的Sequence File

下面主要通过代码理解一下HFile的存储格式。

HFile

下图是HFile的存储格式:

HFile由6部分组成的,其中数据KeyValue保存在Block 0 … N中,其他部分的功能有:确定Block Index的起始位置;确定某个key所在的Block位置(如block index);判断一个key是否在这个HFile中(如Meta Block保存了Bloom Filter信息)。具体代码是在HFile.java中实现的,HFile内容是按照从上到下的顺序写入的(Data Block、Meta Block、File Info、Data Block Index、Meta Block Index、Fixed File Trailer)。

KeyValue: HFile里面的每个KeyValue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。我们来看看里面的具体结构:

开始是两个固定长度的数值,分别表示Key的长度和Value的长度。紧接着是Key,开始是固定长度的数值,表示RowKey的长度,紧接着是 RowKey,然后是固定长度的数值,表示Family的长度,然后是Family,接着是Qualifier,然后是两个固定长度的数值,表示Time Stamp和Key Type(Put/Delete)。Value部分没有这么复杂的结构,就是纯粹的二进制数据了。

Data Block:由DATABLOCKMAGIC和若干个record组成,其中record就是一个KeyValue(key length, value length, key, value),默认大小是64k,小的数据块有利于随机读操作,而大的数据块则有利于scan操作,这是因为读KeyValue的时候,HBase会将查询到的data block全部读到Lru Block Cache中去,而不是仅仅将这个record读到cache中去。

private void append(final byte [] key, final int koffset, final int klength, final byte [] value, final int voffset, final int vlength) throws IOException {

this.out.writeInt(klength);

this.keylength += klength;

this.out.writeInt(vlength);

this.valuelength += vlength;

this.out.write(key, koffset, klength);

this.out.write(value, voffset, vlength);

}

Meta Block:由METABLOCKMAGIC和Bloom Filter信息组成。

public void close() throws IOException {

if (metaNames.size() > 0) {

for (int i = 0 ; i < metaNames.size() ; ++ i ) {

dos.write(METABLOCKMAGIC);

metaData.get(i).write(dos);

}

}

}

File Info: 由MapSize和若干个key/value,这里保存的是HFile的一些基本信息,如hfile.LASTKEY, hfile.AVG_KEY_LEN, hfile.AVG_VALUE_LEN, hfile.COMPARATOR。

private long writeFileInfo(FSDataOutputStream o) throws IOException {

if (this.lastKeyBuffer != null) {

// Make a copy.  The copy is stuffed into HMapWritable.  Needs a clean

// byte buffer.  Won’t take a tuple.

byte [] b = new byte[this.lastKeyLength];

System.arraycopy(this.lastKeyBuffer, this.lastKeyOffset, b, 0, this.lastKeyLength);

appendFileInfo(this.fileinfo, FileInfo.LASTKEY, b, false);

}

int avgKeyLen = this.entryCount == 0? 0: (int)(this.keylength/this.entryCount);

appendFileInfo(this.fileinfo, FileInfo.AVG_KEY_LEN, Bytes.toBytes(avgKeyLen), false);

int avgValueLen = this.entryCount == 0? 0: (int)(this.valuelength/this.entryCount);

appendFileInfo(this.fileinfo, FileInfo.AVG_VALUE_LEN,

Bytes.toBytes(avgValueLen), false);

appendFileInfo(this.fileinfo, FileInfo.COMPARATOR, Bytes.toBytes(this.comparator.getClass().getName()), false);

long pos = o.getPos();

this.fileinfo.write(o);

return pos;

}

Data/Meta Block Index: 由INDEXBLOCKMAGIC和若干个record组成,而每一个record由3个部分组成 — block的起始位置,block的大小,block中的第一个key。

static long writeIndex(final FSDataOutputStream o, final List<byte []> keys, final List<Long> offsets, final List<Integer> sizes) throws IOException {

long pos = o.getPos();

// Don’t write an index if nothing in the index.

if (keys.size() > 0) {

o.write(INDEXBLOCKMAGIC);

// Write the index.

for (int i = 0; i < keys.size(); ++i) {

o.writeLong(offsets.get(i).longValue());

o.writeInt(sizes.get(i).intValue());

byte [] key = keys.get(i);

Bytes.writeByteArray(o, key);

}

}

return pos;

}

Fixed file trailer: 大小固定,主要是可以根据它查找到File Info, Block Index的起始位置。

public void close() throws IOException {

trailer.fileinfoOffset = writeFileInfo(this.outputStream);

trailer.dataIndexOffset = BlockIndex.writeIndex(this.outputStream,

this.blockKeys, this.blockOffsets, this.blockDataSizes);

if (metaNames.size() > 0) {

trailer.metaIndexOffset = BlockIndex.writeIndex(this.outputStream,

this.metaNames, metaOffsets, metaDataSizes);

}

trailer.dataIndexCount = blockKeys.size();

trailer.metaIndexCount = metaNames.size();

trailer.totalUncompressedBytes = totalBytes;

trailer.entryCount = entryCount;

trailer.compressionCodec = this.compressAlgo.ordinal();

trailer.serialize(outputStream);

}

注:上面的代码剪切自HFile.java中的代码,更多信息可以查看Hbase源代码。

转:http://www.tbdata.org/archives/1551

参考:http://www.searchtb.com/2011/01/understanding-hbase.html

http://th30z.blogspot.com/2011/02/hbase-io-hfile.html

分享到:
评论

相关推荐

    MapReduce生成HFile入库到HBase 可能需要的jar包

    MapReduce生成HFile入库到HBase 可能需要的jar包,一共有3个 可以直接放在每台机器的${HADOOP_HOME}/lib下 hadoopHadoop 1.1.2 + hbase 0.94.6.1

    HBASE hfile v2 format

    hbase hfile v2 format draft 描述存储结构

    HFile.java

    HFile.java

    hive-hbase-generatehfiles

    这种模式提供了一种方法,用于获取已存储在Hive中的数据,将其导出为HFile,并从这些HFile批量加载HBase表。概述HFile生成功能已添加到。 它添加了以下属性,然后Hive HBaseStorageHandler可以利用这些属性。 hive....

    hadoop mr file2hfile2hbase

    NULL 博文链接:https://liuyq1991.iteye.com/blog/2109364

    hfile-to-hbase:处女发表

    hfile 到 hbase 处女发表

    MR-read-Hfile2

    这是用于扫描整个hbase表的mapreduce 与TableMapReduceUtil不同,这是直接从HFile读取的 它比TableMapReduceUtil更快

    内存映射存储文件详细算法

    本文档给出了内存映射存储文件详细算法,代码片段: DWORD dwFileSize = GetFileSize(hFile,NULL); HANDLE hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0, dwFileSize+sizeof(char),NULL); if...

    遍历并搜索枚举当前Windows Mobile系统中可用SD卡的源代码

    HANDLE hFile = 0; WIN32_FIND_DATA stLFD = {0}; DWORD dwSumCount = 0; TCHAR athParsePath[MAX_PATH] = {0}; do { if(hFile == 0) { hFile = FindFirstFile(_T("\\*"),&stLFD); ...

    4399大数据笔试题.pdf

    答案:HBase中的所有数据⽂件都存储在Hadoop HDFS⽂件系统上,主要包括上述提出的两种⽂件类型: HFile,HBase中KeyValue数据的存储格式,HFile是Hadoop的⼆进制格式⽂件,实际上StoreFile就是对HFile做了轻量级...

    邮件过滤器代码c/c++

    FILE_HANDLE hFile; char *pBuf=pSession-&gt;pBuf; #define LEN_PRE_BUF 28 #define LEN_PRE_BUF_HALF 12 char szPreBuf[LEN_PRE_BUF]; int nPreLen=0; int nDotPos=0; nBufLen=pSession-&gt;nBufMaxLen-1; hFile=...

    BigGeoDataHBaseLoader:HBase矢量大数据快速入库工具

    2、将要处理的tsv格式数据存储到HDFS上 3、运行MapReduce程序生成HFile hadoop -jar BigGeoDataHbaseLoader.jar class路径 -Dhbase.zookeeper.quorum=zookeeper集群地址 输入空间数据tsv文件路径 输出HFile路径 空间...

    hbase技术介绍

    关于hbase的入门知识.hbase是基于hdfs建立的数据库,可扩展性强。

    read ini file .h file

    read ini file .h file 建议在.h文件中只保留函数的声明,在.cpp文件中重写函数的定义。防止.h文件被多个文件饮用时,编译报错“函数重复定义”

    串口类CSerial

    HANDLE hFile = ::CreateFile&#40;lpszDevice, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0&#41;; // Check if we could open the device if (hFile == INVALID_HANDLE_VALUE) { // ...

    使用程序判断一个文件是否是有效的PE文件.pdf

    // TODO: add draw code for native data here //HANDLE hFile = CreateFile(TEXT("test.png"), GENERIC_ALL, NULL, NULL,OPEN_EXISTING,NULL,NULL); HANDLE hFile = CreateFile(TEXT("notepad.exe"), GENERIC_ALL,...

    Delphi 获取文件访问时间.rar

     if hFile=INVALID_HANDLE_VALUE then  Result:=''  else  begin  GetFileTime(hFile, nil, @WTime, nil);  FileTimeToLocalFileTime(WTime, LTime);  FileTimeToSystemTime(LTime, STime);  Result:=Format...

    使用VC++6.0实现查看dll导出函数名的C++源代码

    CloseHandle(hFile); ::FreeLibrary(hModule); MessageBox("取得函数失败\n"); return ; } ::FreeLibrary(hModule); UnmapViewOfFile(mod_base); CloseHandle(hFileMap); CloseHandle...

    vc6他用api函数CreateFile和WriteFile例子

    HANDLE hFile; hFile=CreateFile(Path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile==INVALID_HANDLE_VALUE){/*continue; //出错时处理*/} DWORD dwWrite; WriteFile(hFile,Data...

    HBase用户手册-v2.2.docx

    7.2.2 用ImportTsv方法生成Hfile 20 7.2.3 利用Hfile进行加载 21 7.2.4 put方式直接加载 22 8 HBase-client 24 8.1 log4j 24 8.2 configuration 25 8.3 Cluster Connections 25 8.4 Connection Pooling 26 8.5 ...

Global site tag (gtag.js) - Google Analytics