深入 HBase 02 - 集群架构:HMaster、RegionServer、ZooKeeper 与 hbase:meta
前置问题与边界
HBase 集群架构最容易被写成一张“Master 管所有、ZooKeeper 存所有、RegionServer 干活”的粗图。这个粗图会误导读写路径。普通数据读写的主路径是 Client 定位 Region 后直连 RegionServer;HMaster 负责表和 Region 的控制面操作;ZooKeeper 保存协调和服务发现所需的短状态;hbase:meta 是 HBase 系统表,保存 Region 路由元数据。
本篇回答一个核心问题:控制面、数据面、协调状态和路由元数据如何分工。Region split、merge 和 assignment 的状态推进放到第 08 篇;客户端缓存、重试和重新定位放到第 09 篇;ServerCrashProcedure 和 WAL 恢复放到第 11 篇。
基础版本仍是 HBase 2.6.6。HBase 2.x 客户端实现存在 ConnectionRegistry 等路径,不能把“客户端总是直接从 ZooKeeper 找全部 Region”写成唯一机制。更稳妥的表述是:客户端通过 registry/元数据定位 hbase:meta 和目标 Region,并缓存 Region location;具体实现随版本和配置演进。
四类职责图
flowchart TD
C[Client] -->|locate and cache| META[hbase:meta table]
C -->|data RPC| RS[RegionServer]
RS --> R[Regions]
HM[HMaster] -->|assignment and admin| R
HM -->|procedure state| PROC[Procedure store]
ZK[ZooKeeper / registry] -->|coordination and service discovery| C
ZK --> HM
HDFS[HDFS] -->|WAL and HFile storage| RS
META -->|region locations| C
图里的箭头不是性能路径排行,而是职责边界。Client 的普通 Get/Put 在定位后走 RegionServer。HMaster 不转发用户数据。ZooKeeper 不保存所有 Region 的持久元数据。HDFS 不理解 HBase 的 Cell、版本和 Region 服务状态。
HMaster:控制面
HMaster 的职责集中在控制面:表创建、删除、schema 变更、Region assignment、RegionServer 失效处理、balancer、procedure 调度。它维护集群元状态,并推动 Region 被分配到某个 RegionServer。
HMaster 不在普通读写的数据路径上。Client 不应该把每次 Put 发送到 HMaster,也不需要 HMaster 参与每次 Get。这和 HDFS 的 NameNode 有相似边界:NameNode 不搬用户数据;HMaster 也不搬 HBase 用户表的普通读写数据。但二者不要混同,NameNode 管 HDFS 文件元数据,HMaster 管 HBase 集群控制面。
RegionServer:数据面
RegionServer 承载 Region。每个 Region 负责一段 row-key range,并在内部按 column family 管理 Store、MemStore、StoreFile、BlockCache 访问和 compaction。Client 定位到 Region 后,把 Get、Put、Delete、Scan 等请求发给对应 RegionServer。
RegionServer 是有状态服务。一个 Region 在同一时刻由一个 RegionServer 提供服务;这个服务点崩溃后,需要 HMaster 通过 procedure 将 Region 重新分配给其他 RegionServer,并处理 WAL split/replay。HDFS 保存底层文件副本,但不会自动让另一个 RegionServer立刻知道如何服务这些 Region。
hbase:meta:路由元数据表
hbase:meta 是 HBase 系统表,保存用户表 Region 的路由信息,例如表名、Region 起止 row key、Region 所在 ServerName 等。Client 定位一行数据时,核心动作是找到覆盖该 row key 的 Region,然后拿到当前负责它的 RegionServer。
把 hbase:meta 写成“配置文件”或“ZooKeeper 里的节点”都不准确。它是 HBase 表,有自己的 Region,也需要被服务。meta 的可用性直接影响新定位和 cache miss 的请求;已经缓存的 Region location 在一定条件下可以继续使用,直到 Region 移动、split、服务异常或缓存过期触发重新定位。
ZooKeeper 和 Registry:协调状态
ZooKeeper 在 HBase 2.x 部署中仍承担协调和服务发现职责,例如活动 Master、部分服务位置、集群状态和会话相关信息。它不是 HBase 用户表元数据的全集,也不保存 HFile 或 WAL。
新版 HBase 客户端路径引入 ConnectionRegistry 等抽象,目的是把“如何找到 Master、meta 或 bootstrap 地址”从客户端主逻辑中分离出来。因此文章应写“客户端通过 registry 和 hbase:meta 完成定位”,不应写成“所有客户端每次都从 ZooKeeper 读 Region 地址”。
HDFS:持久文件层
HBase 的 WAL 和 HFile 通常保存在 HDFS 或兼容 FileSystem。HDFS 提供 block、副本、DataNode、NameNode、pipeline 和文件持久化能力;HBase 在这些文件之上定义表、Cell、版本、Region、WAL replay、compaction 和一致性边界。
当 RegionServer 崩溃时,HDFS 可能仍然完整保存 WAL 和 HFile,但这只解决“文件还在”。HBase 还需要把这些文件重新挂到正确 Region 的服务状态中。
关键对象和状态
| 对象 | 平面 | 保存/推进什么 | 不能误写成 |
|---|---|---|---|
| Client | 访问平面 | Region location cache、RPC 重试 | 每次经 HMaster 转发 |
| HMaster | 控制面 | assignment、表操作、procedure | 普通数据读写代理 |
| RegionServer | 数据面 | Region、MemStore、WAL、StoreFile、BlockCache | 无状态文件网关 |
hbase:meta |
路由元数据 | Region 起止 key 与位置 | ZooKeeper 节点 |
| ZooKeeper/Registry | 协调/发现 | Master、meta/bootstrap、会话状态 | 所有持久元数据 |
| HDFS | 文件层 | WAL、HFile、副本 | HBase 服务语义 |
最小实验
UNVERIFIED_RUNTIME:当前任务环境未运行目标 HBase 集群。以下步骤用于观察架构边界,不提供伪造输出。
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
这组步骤的观察目标是分工:hbase:meta 能看到表 Region 的路由元数据;用户表读写走 lab:t02_arch 的 RegionServer;HDFS 目录里能看到持久文件层,但不能只靠目录解释 Region 当前由谁服务。
清理命令:
1 | |
1 | |
1 | |
失败恢复
一个 RegionServer 宕机后,Client 可能先遇到 RPC 异常或 stale location。HMaster 通过 crash procedure 推进 Region 重新分配,WAL 被 split/replay 后,新的 RegionServer 才能接管对应 Region。hbase:meta 的 Region 位置更新后,Client 清理旧缓存并重新定位。
这里的每一层各管一件事:ZooKeeper/registry 协助发现和存活协调;HMaster 推动 assignment;HDFS 保存 WAL/HFile;hbase:meta 记录 Region location;Client 负责重试和缓存更新。缺一层,读写路径都会出现不同症状。
工程迁移
| HBase 层次 | 迁移问题 | 类比 |
|---|---|---|
| HMaster | 控制面是否参与数据路径 | Kubernetes controller |
| RegionServer | 数据面是否有状态 | shard leader |
hbase:meta |
路由元数据如何查询与缓存 | shard map、tablet metadata |
| ZooKeeper/Registry | bootstrap 与协调状态放哪里 | service registry |
| HDFS | 底层文件和服务语义如何分层 | object store + index service |
[PATTERN] 分布式数据库需要区分四种状态:控制状态、路由状态、协调状态和持久文件状态。把这四类状态混成“元数据”,会让故障分析失去抓手。
常见误解
误解一:HMaster 转发所有读写。普通数据读写定位后直连 RegionServer。
误解二:ZooKeeper 保存所有 HBase 元数据。ZooKeeper/registry 负责协调和发现,Region 路由元数据主要在 hbase:meta。
误解三:hbase:meta 只是普通配置。它是 HBase 系统表,meta 不可用会影响新定位。
误解四:HDFS 负责 HBase Region 恢复。HDFS 保存文件,Region 恢复由 HBase procedure、assignment 和 WAL replay 完成。
误解五:RegionServer 是无状态代理。RegionServer 管理 MemStore、WAL、BlockCache、StoreFile 和 Region 状态。
练习
-
画出一次
get row-1的定位路径,标出 Client、hbase:meta和 RegionServer。 -
解释 HMaster 为什么不应该在普通读写路径上。
-
区分 ZooKeeper 节点、
hbase:meta行、HDFS HFile 三类状态。 -
假设 Region 移动后 Client 仍命中旧缓存,说明它会如何发现并重新定位。
-
观察 Master UI 的 Region 列表,判断其中哪些字段属于控制面,哪些属于路由信息。
系列导航
| 篇号 | 主题 | 状态 |
|---|---|---|
| 00 | 导读:row key 决定数据位置 | |
| 01 | 数据模型:Cell、Column Family 与版本 | 上一篇 |
| 02 | 集群架构:HMaster、RegionServer、ZooKeeper 与 hbase:meta | 本篇 |
| 03 | Schema 与 row key 设计 | 下一篇 |
| 04 | 写入路径:WAL、MVCC、MemStore 与 flush | |
| 05 | 读取路径:BlockCache、Bloom Filter 与 HFile block | |
| 06 | HFile 内部结构 | |
| 07 | Compaction、TTL、版本与 Delete | |
| 08 | Region 生命周期:split、merge 与 assignment | |
| 09 | Client 路由与重试 | |
| 10 | 行级原子性与一致性边界 | |
| 11 | RegionServer 崩溃与 WAL 恢复 | |
| 12 | 跨集群 Replication | |
| 13 | Snapshot、Backup 与恢复 | |
| 14 | Get、Scan、Filter 与分页 | |
| 15 | BufferedMutator 与 Bulk Load | |
| 16 | Coprocessor、Endpoint 与 Phoenix 边界 | |
| 17 | Kerberos、RPC 保护与 ACL | |
| 18 | Metrics、hbtop、Compaction 与性能调优 | |
| 19 | HBase 3.0 与设计边界 |
参考资料
- Apache HBase Architecture:https://hbase.apache.org/docs/architecture/
- Apache HBase Client:https://hbase.apache.org/docs/architecture/client/
- Apache HBase Catalog Tables:https://hbase.apache.org/docs/architecture/catalog-tables/
- Apache HBase Regions:https://hbase.apache.org/docs/architecture/regions/
- Apache HBase RegionServer:https://hbase.apache.org/docs/architecture/regionserver/
- Apache HBase Data Model:https://hbase.apache.org/docs/datamodel/
- Apache HBase 2.6 Client API:https://hbase.apache.org/2.6/apidocs/org/apache/hadoop/hbase/client/package-summary.html
