深入 HBase 08 - Region 生命周期:split、merge 与 assignment
前置问题与边界
本篇回答一个核心问题:表如何扩展,Region 如何迁移,状态由谁推进。
Region 是 HBase 表按 row-key range 切分后的服务单位。它决定数据由哪个 RegionServer 接收,也决定客户端定位和负载均衡的粒度。split、merge 和 assignment 都是在改变 Region 与 RegionServer 的映射,不能把这些动作写成简单的 HDFS 文件移动。
HBase 2.6.6 使用 Procedure v2 和 AssignmentManager 推进 Region assignment。Region 持久状态与位置信息写入 hbase:meta;hbase:meta 自身的位置信息和可用性还涉及 ZooKeeper 或 registry 相关路径。ZooKeeper 不保存所有 HBase 元数据。
生命周期图
stateDiagram-v2
[*] --> CLOSED
CLOSED --> OPENING: assign
OPENING --> OPEN: RegionServer opens region
OPEN --> CLOSING: unassign or move
CLOSING --> CLOSED: close completed
OPEN --> SPLITTING: split requested
SPLITTING --> SPLIT: daughters available
OPEN --> MERGING: merge requested
MERGING --> MERGED: merged region available
SPLIT --> CLOSED
MERGED --> CLOSED
状态图是概念模型。源码和 hbase:meta 中会有更细的 procedure 状态、过渡状态和失败重试记录。文章重点是分工:Master 推进控制面状态,RegionServer 打开或关闭 Region,hbase:meta 记录客户端路由所需信息。
关键对象和状态
| 对象 | 职责 | 不应混淆的边界 |
|---|---|---|
| HMaster | 调度 assignment、split、merge、balancer | 不在普通读写数据路径上 |
| AssignmentManager | 推进 Region 分配状态 | 不是客户端缓存 |
| Procedure v2 | 持久化控制面步骤 | 不是业务事务日志 |
| RegionServer | 打开、关闭并服务 Region | 不决定全局表拓扑 |
hbase:meta |
保存 Region 位置信息和状态 | 不是 ZooKeeper 的替代说法 |
| ZooKeeper / registry | 保存集群协调和入口位置 | 不保存所有表数据或所有 Region 元数据 |
| HDFS | 保存 HFile、WAL、目录 | 不提供 HBase Region 服务语义 |
hbase:meta 是客户端路由的关键表。Region 状态、start key、end key 和当前 server 等信息需要写入 meta,客户端才能定位普通表 Region。hbase:meta 本身也要被定位;这部分是集群引导和元数据可用性的特殊路径。
Split
Region 持续增长后,可以被 split 成两个 daughter Region。split 边界来自 row-key 空间中的某个 split key。split 不是把全部数据立刻复制成两份;HBase 会通过引用、文件视图和后续 compaction 逐步收敛文件布局。
split 的关键风险是热点未必消失。如果 row key 仍然单调递增,新写入可能继续集中到右侧 daughter Region。split 解决的是“一个 Region 过大或过热需要切开”,但 row key 设计决定切开之后压力能否分散。
Merge
Merge 把相邻或可合并的 Region 合成一个更大的 Region。它常用于 Region 过多、空 Region 过多或 split 过度后的治理。merge 同样需要 Master procedure、Region close/open、meta 更新和客户端缓存刷新配合完成。
merge 不应该被当成任意碎片整理命令。Region 合并会影响路由范围、负载分布和短期可用性,需要避开高峰,并结合 Region 大小、StoreFile 数量、compaction backlog 和表访问模式判断。
Assignment 与移动
Assignment 是把某个 Region 分配给某个 RegionServer 并打开服务的过程。move、balance、server crash recovery 都会触发 Region 关闭、重新分配和打开。客户端在这段时间可能收到 Region moved、not serving region 或连接异常,然后刷新缓存并重试。
HMaster 负责推进控制面,但普通 Get 和 Put 不经过 HMaster 转发。客户端缓存 Region 位置后会直接访问 RegionServer。把 Master 写成“所有读写请求的入口”会误导故障定位。
最小实验
UNVERIFIED_RUNTIME:当前任务环境没有目标 HBase 运行条件。以下步骤只描述 HBase 2.6.6 目标环境中的复现路径,不包含伪造输出。
创建带预分区的表,避免依赖写入量触发自动 split:
1 | |
1 | |
1 | |
查看 Region 列表:
1 | |
写入几个落在不同 range 的 row key:
1 | |
1 | |
1 | |
手动 split 某个表或 Region。测试环境可以先对小表执行表级 split,生产环境应按实际 Region 名和负载窗口执行:
1 | |
再次查看 Region:
1 | |
查询 hbase:meta 观察表的 Region 记录。这里只观察行键范围和 server 字段,不把示例输出写成固定形态:
1 | |
清理实验表:
1 | |
1 | |
1 | |
Java Public API 边界
Region 操作应通过 Admin 和 RegionLocator 等 Public API。应用代码可以查询 Region 位置,但不应该写入 hbase:meta 或依赖内部 procedure 类。
1 | |
UNVERIFIED_RUNTIME:示例使用 HBase 2.6.x Public API,但本轮未在目标依赖组合下编译运行。
失败恢复路径
Assignment 失败时,Procedure v2 的持久化步骤使 Master 可以继续推进或重试。RegionServer 在打开 Region 前后失败,系统需要确认 Region 是否已经对外服务、meta 是否已更新、旧 server 是否仍持有该 Region。ServerCrashProcedure 会和 assignment 逻辑协作,让其他 RegionServer 接管 Region 并处理 WAL 恢复。
split 或 merge 中途失败时,HBase 需要在 parent、daughter、merged region、引用文件和 meta 记录之间维持一致。读写请求看到的是某一套可服务的 Region 映射,而不是半更新的 HDFS 目录列表。
工程迁移
| HBase 机制 | 通用模式 | 迁移场景 |
|---|---|---|
| Region | 有序 key range 分片 | Bigtable tablet、TiKV Region、分片数据库 range shard |
| Assignment | 控制面推进服务归属 | 分区 leader 调度、Kafka partition reassignment |
hbase:meta |
路由目录 | 元数据表、placement map、service discovery registry |
| Procedure v2 | 可恢复控制面工作流 | DDL job、rebalance job、分片迁移任务 |
模式公式是:serve(range) = assign(range, server) + publish(location) + refresh(client_cache)。听到“分片移动后请求打到旧节点”,先查路由发布和客户端缓存刷新,不要只查底层文件是否存在。
常见误解
| 误解 | 更准确的说法 |
|---|---|
| split 会立刻重写所有 HFile | split 可以通过引用和后续 compaction 收敛文件,不等于立即全量复制 |
| Master 转发所有读写 | 普通读写由客户端直连 RegionServer,Master 管控制面 |
| ZooKeeper 保存所有 HBase 元数据 | Region 路由元数据主要在 hbase:meta,ZooKeeper/registry 管入口和协调状态 |
| merge 只是节省目录数量 | merge 改变 row-key range、负载分布和客户端路由 |
| Region 越多越好 | Region 过多会增加 Master、RegionServer、meta 和 compaction 压力 |
练习
- 创建预分区表,写入不同前缀 row key,观察 Region 分布。
- 对单调递增 row key 做 split,判断热点是否真正分散。
- 在测试集群移动 Region,观察客户端重试和 meta 变化。
- 合并两个低流量 Region 前,列出需要检查的 StoreFile、请求量和 compaction 指标。
系列导航
参考资料
- Apache HBase Reference Guide:Architecture、Regions、Catalog Tables、Master、RegionServer:https://hbase.apache.org/docs/
- Apache HBase 2.6 User API:
Admin、RegionLocator:https://hbase.apache.org/2.6/apidocs/ - Apache HBase 源码 rel/2.6.6:AssignmentManager、Procedure v2、SplitTableRegionProcedure、MergeTableRegionsProcedure:https://github.com/apache/hbase/tree/rel/2.6.6
- Apache HBase JIRA:HBASE-14614、HBASE-11546 相关 assignment 与 procedure 演进:https://issues.apache.org/jira/projects/HBASE
- Apache Hadoop 3.4.3 HDFS 文档:https://hadoop.apache.org/docs/r3.4.3/
