HBase数据存储模型 #
一、LSM Tree概述 #
HBase基于LSM Tree(Log-Structured Merge Tree)实现数据存储,这是一种针对写入优化的数据结构。
1.1 LSM Tree原理 #
text
┌─────────────────────────────────────────────────────────────────────┐
│ LSM Tree 原理 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 写入流程: │
│ ┌─────────┐ ┌──────────┐ ┌───────────────────────────┐ │
│ │ Write │ ───► │ MemStore │ ───► │ StoreFile (HFile) │ │
│ │ Request │ │ (内存) │ │ (磁盘) │ │
│ └─────────┘ └──────────┘ └───────────────────────────┘ │
│ │ │ │
│ │ Flush │ Compaction │
│ ▼ ▼ │
│ ┌──────────┐ ┌───────────┐ │
│ │ WAL │ │ 合并文件 │ │
│ │ (日志) │ │ 清理数据 │ │
│ └──────────┘ └───────────┘ │
│ │
│ 优势: │
│ - 写入性能高(顺序写) │
│ - 支持大数据量存储 │
│ - 自动合并优化查询 │
│ │
└─────────────────────────────────────────────────────────────────────┘
1.2 LSM Tree vs B+ Tree #
| 特性 | LSM Tree | B+ Tree |
|---|---|---|
| 写入方式 | 顺序写 | 随机写 |
| 写入性能 | 极高 | 较低 |
| 读取性能 | 需合并查询 | 高 |
| 空间利用 | 有写放大 | 较高 |
| 适用场景 | 写多读少 | 读写均衡 |
二、MemStore #
2.1 MemStore概述 #
MemStore是HBase的内存写缓存,所有写入操作首先写入MemStore。
text
┌─────────────────────────────────────────────────────────────────────┐
│ MemStore 结构 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ RegionServer │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Region │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ Store (Column Family) │ │ │
│ │ │ ┌─────────────────────────────────────────────────────┐│ │ │
│ │ │ │ MemStore ││ │ │
│ │ │ │ ┌───────────────────────────────────────────────┐ ││ │ │
│ │ │ │ │ SkipList (有序数据结构) │ ││ │ │
│ │ │ │ │ ┌─────┐ │ ││ │ │
│ │ │ │ │ │row3 │ cf:col → value3 │ ││ │ │
│ │ │ │ │ ├─────┤ │ ││ │ │
│ │ │ │ │ │row2 │ cf:col → value2 │ ││ │ │
│ │ │ │ │ ├─────┤ │ ││ │ │
│ │ │ │ │ │row1 │ cf:col → value1 │ ││ │ │
│ │ │ │ │ └─────┘ │ ││ │ │
│ │ │ │ └───────────────────────────────────────────────┘ ││ │ │
│ │ │ └─────────────────────────────────────────────────────┘│ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
2.2 MemStore特性 #
text
MemStore特性
├── 数据结构
│ └── SkipList(跳表),保证有序性
│
├── 内存管理
│ ├── 默认128MB刷新阈值
│ └── 占用堆内存比例可配置
│
├── 数据排序
│ └── 按RowKey、CF、CQ、Timestamp排序
│
└── 刷新触发条件
├── MemStore大小达到阈值
├── RegionServer全局内存压力
├── 手动触发
└── 时间间隔触发
2.3 MemStore配置 #
xml
<!-- hbase-site.xml -->
<!-- MemStore刷新阈值 -->
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>134217728</value> <!-- 128MB -->
</property>
<!-- RegionServer全局MemStore大小比例 -->
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value>0.4</value>
</property>
<!-- 低水位比例 -->
<property>
<name>hbase.regionserver.global.memstore.size.lower.limit</name>
<value>0.95</value>
</property>
<!-- MemStore本地聚合缓冲区 -->
<property>
<name>hbase.hregion.memstore.mvcc.max</name>
<value>10</value>
</property>
2.4 Flush流程 #
text
┌─────────────────────────────────────────────────────────────────────┐
│ Flush 流程 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 触发条件: │
│ 1. MemStore达到128MB │
│ 2. RegionServer全局MemStore达到高水位 │
│ 3. 手动触发 flush 'table_name' │
│ 4. WAL日志数量过多 │
│ │
│ Flush流程: │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ MemStore │ ─► │ 准备阶段 │ ─► │ 写HFile │ ─► │ 更新元数据│ │
│ │ │ │ 阻塞写入 │ │ 写磁盘 │ │ 清空内存 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ 注意: │
│ - Flush期间写入会阻塞(短暂) │
│ - 生成新的HFile文件 │
│ - 更新StoreFile列表 │
│ │
└─────────────────────────────────────────────────────────────────────┘
三、StoreFile与HFile #
3.1 StoreFile概述 #
StoreFile是HBase中HFile的逻辑表示,每个StoreFile对应一个HFile文件。
text
Store
├── MemStore (内存)
└── StoreFiles (磁盘)
├── StoreFile 1 (HFile 1)
├── StoreFile 2 (HFile 2)
├── StoreFile 3 (HFile 3)
└── ...
3.2 HFile结构 #
text
┌─────────────────────────────────────────────────────────────────────┐
│ HFile 结构 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ HFile v3 │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ File Info │ │ │
│ │ │ - lastKey, avgKeyLen, avgValueLen │ │ │
│ │ │ - compression, encryption │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Data Block 1 │ │ │
│ │ │ ┌─────┬──────────────────────────────────────┐ │ │ │
│ │ │ │ KV │ Key | Value | Type | Timestamp │ │ │ │
│ │ │ │ 1 │ row1| val1 | Put | 1704067200 │ │ │ │
│ │ │ │ 2 │ row2| val2 | Put | 1704067201 │ │ │ │
│ │ │ └─────┴──────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Data Block 2 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ ... │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Meta Block │ │ │
│ │ │ - Bloom Filter Data │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Load-on-open │ │ │
│ │ │ - Root Data Index │ │ │
│ │ │ - File Info │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Trailer │ │ │
│ │ │ - File Info Offset │ │ │
│ │ │ - Compression Codec │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
3.3 HFile Block类型 #
| Block类型 | 说明 |
|---|---|
| Data Block | 存储实际KV数据 |
| Index Block | 数据索引,快速定位 |
| Bloom Block | 布隆过滤器数据 |
| Meta Block | 元数据信息 |
| File Info | 文件信息 |
3.4 KeyValue格式 #
text
┌─────────────────────────────────────────────────────────────────────┐
│ KeyValue 格式 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Key Length │ Value Length │ Key │ Type │ Timestamp │ Value │ │
│ │ (4 bytes) │ (4 bytes) │ │(1 B) │ (8 bytes) │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ Key结构: │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Row Length │ RowKey │ CF Length │ CF │ CQ Length │ CQ │ TS │ │
│ │ (2 bytes) │ │ (1 byte) │ │ (2 bytes) │ │(8 B) │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ Type类型: │
│ ├── Put - 写入 │
│ ├── Delete - 删除列 │
│ ├── DeleteFamily - 删除列族 │
│ └── DeleteFamilyVersion - 删除列族版本 │
│ │
└─────────────────────────────────────────────────────────────────────┘
四、WAL(Write-Ahead Log) #
4.1 WAL概述 #
WAL是HBase的写前日志,保证数据不丢失。
text
┌─────────────────────────────────────────────────────────────────────┐
│ WAL 机制 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 写入流程: │
│ │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Write │ ───► │ WAL │ ───► │ MemStore │ │
│ │ Request │ │ (磁盘) │ │ (内存) │ │
│ └─────────┘ └──────────┘ └──────────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ 返回成功 │ │
│ └──────────┘ │
│ │
│ 故障恢复: │
│ RegionServer故障后,新节点读取WAL重放数据 │
│ │
└─────────────────────────────────────────────────────────────────────┘
4.2 WAL类型 #
| 类型 | 说明 | 适用场景 |
|---|---|---|
| SYNC | 同步写入,等待磁盘确认 | 强一致性要求 |
| ASYNC | 异步写入,不等待确认 | 高性能要求 |
| SYNC_WAL | 同步WAL | 默认配置 |
4.3 WAL配置 #
xml
<!-- hbase-site.xml -->
<!-- WAL存储目录 -->
<property>
<name>hbase.wal.dir</name>
<value>/hbase/WALs</value>
</property>
<!-- WAL滚动大小 -->
<property>
<name>hbase.regionserver.logroll.period</name>
<value>3600000</value> <!-- 1小时 -->
</property>
<!-- WAL最大文件数 -->
<property>
<name>hbase.regionserver.maxlogs</name>
<value>32</value>
</property>
五、Compaction #
5.1 Compaction概述 #
Compaction是HBase合并StoreFile的过程,分为Minor和Major两种。
text
┌─────────────────────────────────────────────────────────────────────┐
│ Compaction 类型 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Minor Compaction(小合并) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ StoreFile 1 + StoreFile 2 + StoreFile 3 → StoreFile New │ │
│ │ │ │
│ │ 特点: │ │
│ │ - 合并部分小文件 │ │
│ │ - 不删除过期数据 │ │
│ │ - 执行频率高 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ Major Compaction(大合并) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ All StoreFiles → One StoreFile │ │
│ │ │ │
│ │ 特点: │ │
│ │ - 合并所有文件 │ │
│ │ - 删除过期数据(TTL、标记删除) │ │
│ │ - 执行频率低,资源消耗大 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
5.2 Compaction触发条件 #
text
触发条件
├── Minor Compaction
│ ├── StoreFile数量达到阈值
│ ├── MemStore Flush后
│ └── 手动触发
│
└── Major Compaction
├── 定时触发(默认7天)
├── 手动触发
└── Region合并后
5.3 Compaction配置 #
xml
<!-- hbase-site.xml -->
<!-- Minor Compaction文件数阈值 -->
<property>
<name>hbase.hstore.compaction.min</name>
<value>3</value>
</property>
<!-- Major Compaction间隔(毫秒) -->
<property>
<name>hbase.hregion.majorcompaction</name>
<value>604800000</value> <!-- 7天 -->
</property>
<!-- 禁用自动Major Compaction -->
<property>
<name>hbase.hregion.majorcompaction</name>
<value>0</value>
</property>
<!-- Compaction线程数 -->
<property>
<name>hbase.regionserver.thread.compaction.throttle</name>
<value>2</value>
</property>
六、BlockCache #
6.1 BlockCache概述 #
BlockCache是HBase的读缓存,缓存HFile数据块。
text
┌─────────────────────────────────────────────────────────────────────┐
│ BlockCache 结构 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ RegionServer 堆内存 │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌────────────────────┐ ┌────────────────────┐ │ │
│ │ │ MemStore (40%) │ │ BlockCache (40%) │ │ │
│ │ │ │ │ │ │ │
│ │ │ 写缓存 │ │ 读缓存 │ │ │
│ │ │ 存储待刷新数据 │ │ 缓存热数据块 │ │ │
│ │ └────────────────────┘ └────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────────┐ │ │
│ │ │ 其他内存 (20%) │ │ │
│ │ └────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
6.2 BlockCache实现 #
| 实现 | 说明 | 适用场景 |
|---|---|---|
| LruBlockCache | LRU算法,堆内内存 | 默认配置 |
| BucketCache | 堆外内存,减少GC | 大内存场景 |
| CombinedBlockCache | LruBlockCache + BucketCache | 平衡场景 |
6.3 BlockCache配置 #
xml
<!-- hbase-site.xml -->
<!-- BlockCache大小比例 -->
<property>
<name>hfile.block.cache.size</name>
<value>0.4</value>
</property>
<!-- 启用BucketCache -->
<property>
<name>hbase.bucketcache.ioengine</name>
<value>offheap</value>
</property>
<!-- BucketCache大小 -->
<property>
<name>hbase.bucketcache.size</name>
<value>8192</value> <!-- MB -->
</property>
七、数据读取路径 #
7.1 读取流程详解 #
text
┌─────────────────────────────────────────────────────────────────────┐
│ 数据读取路径 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 读取请求 │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 1. 检查 BlockCache │ │
│ │ ├── 命中 → 返回数据 │ │
│ │ └── 未命中 → 继续 │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 2. 检查 MemStore │ │
│ │ ├── 找到 → 返回数据 │ │
│ │ └── 未找到 → 继续 │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 3. 检查 Bloom Filter │ │
│ │ ├── 可能存在 → 继续 │ │
│ │ └── 不存在 → 跳过该HFile │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 4. 查询 HFile │ │
│ │ ├── 使用索引定位Block │ │
│ │ ├── 读取Data Block │ │
│ │ └── 放入BlockCache │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 5. 合并结果 │ │
│ │ └── 合并多个版本,返回最新数据 │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
八、总结 #
本节介绍了HBase的数据存储模型:
| 组件 | 功能 |
|---|---|
| LSM Tree | 写入优化的数据结构基础 |
| MemStore | 内存写缓存,有序存储 |
| HFile | 磁盘存储格式,块结构 |
| WAL | 写前日志,保证数据安全 |
| Compaction | 合并文件,优化查询 |
| BlockCache | 读缓存,加速数据访问 |
下一步,让我们学习Region与RegionServer!
最后更新:2026-03-27