HBase 深度解析:Bigtable 的开源实现,PB 级结构化数据的答案
数据量到了 PB 级,关系型数据库就扛不住了——分库分表太复杂、单表查询太慢、列扩展要改 schema。
HBase 就是为这个场景设计的:一个建立在 HDFS 之上的分布式列式数据库,专治”海量结构化数据 + 高并发读写”。
它是 Google Bigtable 的开源实现——数据模型一样、架构一样、连核心概念都是对应的。
HBase 的数据模型:一张三维的稀疏大表
HBase 的数据模型和 Bigtable 一样,可以理解为:
一个多维的、稀疏的、分布式的映射表。
1 | (RowKey, Column Family:Qualifier, Timestamp) → Value |
四个核心概念:
| 概念 | 说明 |
|---|---|
| RowKey | 行唯一标识,按字典序排序,所有查询依赖它 |
| 列族(Column Family) | 表创建时定义,是存储和权限的基本单位 |
| 列(Qualifier) | 列族下的具体字段,可以动态添加 |
| 时间戳(Timestamp) | 每个单元格可存多个版本,按时间戳区分 |
RowKey 为什么重要? HBase 没有二级索引,所有查询要么靠 RowKey 精确匹配,要么靠 RowKey 范围扫描。RowKey 设计直接决定了查询能不能跑得快。
列族为什么重要? 同一列族的数据物理上存在一起。查询时只扫目标列族,不用读整行。
系统架构:Master 管调度,RegionServer 存数据
HBase 是主从架构,四个角色分工明确:

| 角色 | 管什么 |
|---|---|
| HMaster | 表创建/删除、Region 分配、负载均衡、故障恢复 |
| RegionServer | 处理读写请求、管理 Region、刷写 MemStore、合并 StoreFile |
| ZooKeeper | Master 选举、监控 RegionServer 上下线、存元数据入口 |
| HDFS | 持久化存储(StoreFile + HLog) |
关键设计:HMaster 不参与读写请求。 客户端直接连 RegionServer 读写数据,Master 只做调度和管理,压力小。
数据怎么存:Region → Store → MemStore → StoreFile
层级关系:
text
1 | Table |
写入流程:
- Client 写数据 → 先写 HLog(WAL)(持久化到 HDFS)
- 再写 MemStore(内存)
- MemStore 满了(默认 128MB)→ 刷写成 StoreFile(HDFS)
- 多个小 StoreFile → 定期合并成大文件(Compaction)
HLog 的作用: RegionServer 挂了,还没刷写的 MemStore 数据可以通过 HLog 恢复。数据不丢。
读写流程
读:
- Client 先查 ZooKeeper 找元数据
- 从元数据表找到目标 Region 在哪个 RegionServer
- Client 直连 RegionServer
- 查询顺序:BlockCache → MemStore → StoreFile(先查缓存,再查内存,最后查磁盘)
写:
- Client 定位到目标 RegionServer
- 先写 HLog(持久化)
- 再写 MemStore(内存)
- 返回 Client 成功
为什么写入快? 写操作只涉及顺序写 HLog + 内存写 MemStore,不涉及随机磁盘 IO。为什么读取不慢? 有 BlockCache + MemStore 两层缓存,大部分热数据在内存里。
列式存储 vs 行存储
| 行存储(MySQL) | 列式存储(HBase) | |
|---|---|---|
| 存储方式 | 一行所有列在一起 | 同一列族的数据在一起 |
| 查询部分列 | 扫描整行 | 只读目标列族 |
| 列扩展 | 改 schema | 动态加列,空列不占空间 |
| 适合场景 | 事务、小数据量、固定列 | 海量数据、稀疏列、列级查询频繁 |
HBase 的”列式”不是真正的列存(像 Parquet 那种),而是”列族式”——同一列族物理相邻,列族之间分离。 它比行存储更适合”只查部分字段”的场景,但不如 Parquet 那种纯列存适合分析型查询。
什么时候用 HBase,什么时候不用
适合:
| 场景 | 原因 |
|---|---|
| 数据量大(TB/PB 级) | 架在 HDFS 上,海量存储是天生能力 |
| 列动态变化 | 列可以随时加,不用改 schema |
| 高并发随机读写 | 内存缓存 + 分布式,扛得住 |
| 按 RowKey 范围查询 | RowKey 排序,范围扫描高效 |
| 强一致性要求 | 单行操作强一致 |
不适合:
| 场景 | 原因 |
|---|---|
| 需要二级索引 | 只有 RowKey 索引,其他列没法直接查 |
| 需要 JOIN | 不支持表关联 |
| 事务(多行 ACID) | 只支持单行事务 |
| 数据量小(GB 级) | 分布式调度开销大于收益 |
| 实时分析 SQL | 用 HBase 做分析不如 Parquet + Presto |