对 HBase 表存储层次梳理
前言
HBase 表是由一个或者多个 region 组成,一个 region 由一个或者多个列蔟组成,一个列蔟由一个 store 组成,一个 store 由唯一 memstore 加上一个或者多个 HFile 组成,HFile 又是由 block 组成,而 block 是由多个 cell 组成。
概述
Region
Region 类似于数据库的分片和分区的概念,每个 Region 负责一小部分 Rowkey 范围的数据的读写和维护,这样即使是一张巨大的表,由于被切割到不同的 Region,访问起来的时延也很低。
Region 包含了对应的起始行到结束行的所有信息。
Store
Store 是存储所有写入表中信息的实体,并且当数据需要从表中读取时也将被用到。A Store is the same thing as a ColumnFamily. 一个 Store 等价一个列簇
Memstore
HBase 是基于 LSM-Tree 模型的,所有的数据更新插入操作都首先写入 Memstore 中(同时会顺序写到日志HLog中),达到指定大小之后再将这些修改操作批量写入磁盘,生成一个新的 HFile 文件,这种设计可以极大地提升 HBase 的写入性能。每一个 Store 里面都有一个 Memstore, MemStore 保存对 Store 的内存修改。修改是 Cells / KeyValues。
StoreFile
StoreFile 为 HFile 上的一层类封装。A StoreFile is a facade of HFile.
HFile
HFile 对应的列蔟。当内存写满必须要刷新到磁盘时,HFile 就会被创建,所以 HFile 存放的是某个时刻的 MemStore 刷写时的快照,一个完整的行的数据可能存放在多个 HFile 里。 随着时间推移,HFile 最终会被压缩(即合并)成大文件。HFile 是 HBase 用来存储数据的文件格式。
HFile 由不同种类的 block 块组成(索引块和数据块)。HFile 存储在 HDFS 上,因此获得 HDFS 的持久化和多副本的优势。
Block
HFile 由 block 组成,不要与 HDFS 的 block 混淆了。一个 HDFS 数据块可以包含很多 HFile block。HFile block 通常在 8kb 和 1MB 之间,默认大小是 64kb(在建表语句中可以通过参数 BlockSize 指定)。如果一个表配置了压缩选项,HBase 仍会产生了 64kb 大小 block,然后压缩 block。根据数据的大小以及压缩格式,压缩后的 block 存储在磁盘的大小也不一样。
每个 block 的大小可以在创建表列簇的时候通过参数 blocksize => '65535'
进行指定,默认为 64k,大号的 Block 有利于顺序 Scan,小号 Block 利于随机查询,因而需要权衡。
如果将 block size 配置得很小,将会产生过多的 HFile block 索引,这将会给内存造成压力 (《HBase 实战》P27 《HBase应用架构》P19)
KeyValue
KeyValue 是 HBase 数据存储的核心,KeyValue 并不是简单的 KV 数据对,是一个具有复杂元素的结构体
由 keylength、valuelength、key、value 四个部分组成,其中 Key 又由 Row Length、Row、Column Family Length、Column Family、Column Qualifier、TimeStamp、Key Type 七部分组成。
字段 | 说明 | 长度 |
---|---|---|
Key Length | 存储Key的长度 | 4个字节 |
Value Length | 存储Value的长度 | 4个字节
Row Length | 存储 Row 的长度,即 Rowkey 的长度 | 2个字节
Row | 存储 Rowkey | Row Length
Column Family Length | 存储列簇 Column Family 的长度 | 1个字节
Column Family | 存储 Column Family 实际内容 | Column Family Length
Column Qualifier | 存储 Column Qualifier 对应的数据 | -
Time Stamp | 存储时间戳 TimeStamp | 8个字节
Key Type | 存储 Key 类型 KeyType | 1个字节
Value | 存储单元格 Cell 对应的实际的值Value | Value Length
“key type” 字段代表不同可能的HBase操作
- Put
- Delete
- DeleteColumn
- DeleteFamily
KeyValue 保存了这个 value 的所有信息,这也是为什么面向列的原因
Q: Row,Column Family 都有一个 length 标志,为什么 Column Qualifier 没有呢?
A: 由于 Key 中其它的字段占用大小已经知道,并且知道整个 Key 的大小,因此没有存储 Column Qualifier 的大小。 Column Qualifier 的 Length 可以由 key length 减去其他 length 得到,这样可以减少一定的存储量。
参考链接