HBase 架构 | 存储

目前主流的RDBMS和其他非关系型数据库底层数据库结构大都会使用B树或B+树,有时还会使用LSM树(Log-Structured Tree)。HBase与BitTable一样,是基于LSM树的系统。
基本结构 为了了解HBase存储层,下图给出了一个顶层结构图。
HBase 架构 | 存储
文章图片

从上图中可以看到HBase主要处理两种文件,预写日志(WAL)实际文件。这两种文件主要由HRegionServer管理。在某些情况下,HMaster也可以进行一些低层的文件操作。当存储数据到HDFS中时,数据文件会被切分成更小的块。
一个基本的流程分为三步:

  1. 通过ZooKeeper查询到含有-ROOT-的region server A
  2. 通过region server A查询到含有.META.表中对应的region server B
  3. 通过region server B查询到行健信息
事实上,查找region服务器A和region服务器B的主要内容(比如region的位置)都被缓存下来了,因此只会被查询一次,同时直接联系管理实际数据HRegionServer。所以之后客户端可以直接通过缓存信息很好的定位所需的数据位置,而不用再次查找.META.表。
-ROOT-存在于zookeeper上,类似于RDBMS里的database这个概念,可以更好的做权限管理和安全控制;
.META.的信息作为一种Region存放在Region Server上。
在新版本的HBase里面,-ROOT-表已经改名为hbase:namespace.META.表改名为hbase:meta
查看-ROOT- 启动zookeeper client,可以使用ls /hbase/namespace 查询得到
启动hbase shell,可以使用scan 'hbase:namespace'查询得到
查看.META. 启动hbase shell,可以使用scan 'hbase:meta'查询得到
文件 目录结构
. ├── habse.version ├── hbase.id ├── .logs ├── .corrupt ├── splitlog └── data └── default ├── t1 │├── f1f21fee947157f277b042f11d127e82 ││├── .regioninfo ││├── c1 │││└── 5201b34c76d646c2870c58949f54e776 ││└── splits │├── .tabledesc ││└── .tableinfo.0000000001 │└── .tmp └── testtable ├── 2e1f76c4bf66f2e2c16cff1b1a676bbd │├── .regioninfo │├── colfam1 │├── recovered.edits ││└── 2.seqid │├── splits │└── .tmp ├── .tabledesc │└── .tableinfo.0000000001 └── .tmp

HBase使用一个HDFS中可配置的根目录,用户可以使用hdfs命令来查看,也可以使用hue这款工具来查询,这里使用hue进行示范。
文件可以被分为两类,一类位于HBase根目录下,另一类位于根目录中的表目录下。
根级文件 HBase 架构 | 存储
文章图片

目录/文件名 用途
wals 由HLog实例管理,存放在“目录结构”中的.log目录中
hbase.id 文件包含集群唯一的ID和文件格式版本信息
hbase.version 文件格式版本信息
splitlog 存储日志拆分过程中产生的中间拆分文件
corrupt 存储日志拆分过程中产生的中间损坏日志
表级文件 HBase 架构 | 存储
文章图片

在HBase中,每张表都有自己的目录,其位于文件系统的HBase根目录下。
目录/文件名 用途
.tabledesc 存储相应的表序列化后的HTableDescriptor
.tmp 临时数据,比如更新.tableinfo文件时生成的临时数据
md5.. region级文件
.tableinfo文件在.tabledesc目录里面
region级文件 HBase 架构 | 存储
文章图片

region级文件位于表目录里面。region级文件的目录时一部分region名字的MD5散列值。
目录/文件名 用途
.regioninfo 对应region的HRegionInfo实例反序列化的信息
recovered.edits 存放临时的拆分文件
- 在WAL回收时,任何未提交的修改都会被写入到每个region的一个单独的文件(splitlog)中。
- 将上述文件移动到临时的recovered.edits文件中
- 若region被打开,region服务器将会看到需要恢复的文件,并放回其中对应的条目
一旦region超过了配置中region大小的最大值,region就需要拆分,其会创建一个对应的splits目录,它被用来临时存放两个region相关的数据。如果拆分成功(通常这个过程持续几秒或更短),之后它们会被移动到表目录中,并形成两个新的region,每个region代表原始值的一半。
当用户看到region的目录中:
- 没有.tmp目录,意味着还没有进行过压缩操作
- 没有recovered.edits目录,意味着WAL没有进行过回放操作
region拆分
在拆分过程中,所有的步骤在ZooKeeper中都进行跟踪,这使得一个服务器失效时,其他进程可以直到这个region的状态。
HBase 架构 | 存储
文章图片

region合并
存储文件会被后台的管理进程仔细的监控起来以确保它们处于控制值夏,随着memstore的写入会生成很多的磁盘文件,如果文件的数目达到阈值,合并过程将会把它们合并成数量更少,体积更大的文件。这个过程持续到这些文件超过配置的最大存储文件大小,会触发一个region拆分
压缩合并有两种,即minor和major。
  • minor合并负责重写最后生成的几个文件到一个更大的文件中。
  • major合并会将所有文件压缩成一个单独的文件,在执行压缩检查时,系统自动决定运行哪种合并。
minor合并可以处理的最大文件数量默认是10,用户可以通过hbase.hstore.compaction.max来配置。
如果海没有达到major合并的执行周期,系统会选择minor合并执行。当minor合并包括所有的存储文件,且所有文件均未达到设置的每次压缩的最大文件数时,minor合并可能被提升成major合并。
HFile 格式 实际的存储文件功能是由HFile类实现的,它被专门创建达到一个目的:有效的存储HBase的数据。它们基于Hadoop的TFile类。HFile参考BigTable的SSTable和Hadoop的TFile实现,从HBase开始到现在,HFile经历了三个版本,其中V2在0.92引入,V3在0.98引入。这里我们看下V1的格式。
HBase 架构 | 存储
文章图片

这些文件是可变长度的,唯一固定的块是File Info块和Trailer块。如上图所示:
Trailer有指向其他块的指针,它是在持久化数据到文件结束时写入的,写入后即确定其成为不可变的数据存储文件。
Index块记录Data和Meta块的偏移量。
Data和Meta块实际上都是可选的,但是考虑到HBase如何使用数据文件,在存储文件中用户几乎总能找到Data块。
在HDFS中,文件的默认块大小是64MB(现默认是128MB),这个是HFile默认块大小的1024倍,因此HBase存储文件的块与Hadoop的块之间并没有匹配关系。事实上,这两种块类型之间根本没有相关性。HBase把它的文件透明的存储到文件系统中,而HDFS也使用块来切分文件仅仅是一个巧合,并且HDFS并不知道HBase中存储的是什么。
下图描述了逻辑上把一个单元格的数据存储到一张表中,到实际存储到HDFS的映射过程。
HBase 架构 | 存储
文章图片

KeyValue格式 HBase 架构 | 存储
文章图片

KeyValue类是HBase中数据存储的核心,由keylengthvaluelengthkeyvalue四个部分组成。
其中Key又由Row LengthRow、Column Family LengthColumn FamilyColumn QualifierTime StampKey Type七部分组成。
KeyValue不会在块之间拆分。例如,如果有一个8 MB的KeyValue,即使块大小是64kb,这个KeyValue将作为一个连续块读取。
  • KeyLength存储Key的长度,占4B;
  • ValueLength存储Value的长度,占4B;
Key存储具体的Cell数据
Key 作用
Row Length 存储rowkey的长度,占2B (Bytes.SIZEOF_INT)
Row 存储Rowkey实际内容,其大小为Row Length
Column Family Length 存储列簇Column Family的长度,占1B (Bytes.SIZEOF_BYTE)
Column Family 存储Column Family实际内容,大小为Column Family Length
Column Qualifier 存储Column Qualifier对应的数据
Time Stamp 存储时间戳Time Stamp,占8B (Bytes.SIZEOF_LONG)
Key Type 存储Key类型Key Type,占1B ( Bytes.SIZEOF_BYTE),Type分为Put、Delete、DeleteColumn、DeleteFamilyVersion、DeleteFamily、Maximum、Minimum等类型,标记这个KeyValue的类型
由于Key中其它的字段占用大小已经知道,并且知道整个Key的大小,因此没有存储Column Qualifier的大小。
Value存储单元格Cell对应的实际的值Value 示例 【HBase 架构 | 存储】对于Put: rowkey=row1, cf:attr1=value1操作,Key对应关系如下:
key value
rowlength 4
row row1
columnfamilylength 2
columnfamily cf
columnqualifier attr1
timestamp server time of Put
keytype Put

    推荐阅读