前置问题与边界

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
hbase shell
1
create_namespace 'lab'
1
create 'lab:t02_arch', 'cf'
1
put 'lab:t02_arch', 'row-1', 'cf:q', 'v'
1
scan 'hbase:meta', {FILTER => "PrefixFilter('lab:t02_arch')"}
1
get 'lab:t02_arch', 'row-1'
1
hdfs dfs -ls -R /hbase/data/lab/t02_arch

这组步骤的观察目标是分工:hbase:meta 能看到表 Region 的路由元数据;用户表读写走 lab:t02_arch 的 RegionServer;HDFS 目录里能看到持久文件层,但不能只靠目录解释 Region 当前由谁服务。

清理命令:

1
disable 'lab:t02_arch'
1
drop 'lab:t02_arch'
1
drop_namespace 'lab'

失败恢复

一个 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 状态。

练习

  1. 画出一次 get row-1 的定位路径,标出 Client、hbase:meta 和 RegionServer。

  2. 解释 HMaster 为什么不应该在普通读写路径上。

  3. 区分 ZooKeeper 节点、hbase:meta 行、HDFS HFile 三类状态。

  4. 假设 Region 移动后 Client 仍命中旧缓存,说明它会如何发现并重新定位。

  5. 观察 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 与设计边界

参考资料