Article

列式数据库HBase

更新于:2026-07-16

第一章:HBase 概述

1.1 什么是 HBase

概念名称说明注意事项
HBase 定义HBase 是一个分布式的、面向列的开源 NoSQL 数据库,构建在 Hadoop HDFS 之上,支持海量数据的随机实时读写。HBase 并非传统数据库,不支持 SQL(原生),需通过 Phoenix 等工具提供 SQL 支持。
开源与生态属于 Apache 软件基金会顶级项目,是 Hadoop 生态系统的重要组成部分。依赖 Hadoop(尤其是 HDFS)和 ZooKeeper,不能独立运行于普通文件系统。
设计目标高可靠性、高扩展性、强一致性、低延迟访问,适用于 PB 级结构化/半结构化数据存储。不适合复杂事务(如多行 ACID)、频繁 JOIN 或复杂查询场景。
典型应用场景时序数据(如监控日志)、用户画像、推荐系统、消息系统、实时分析等。行键设计对性能影响极大,需提前规划。

1.2 HBase 与传统关系型数据库的区别

概念名称说明注意事项
数据模型HBase 是稀疏、多维映射表(Key-Value 形式),按列族存储;关系型数据库基于行存储的二维表。HBase 表无需预定义列(除列族外),列可动态增加。
Schema 灵活性HBase 是 schema-less(列族需预定义,但列限定符可动态添加);关系型数据库需严格预定义表结构。列族数量建议控制在个位数(通常 1~3 个),因每个列族对应一个 StoreFile。
事务支持HBase 仅支持单行 ACID 事务;关系型数据库支持跨行/跨表 ACID 事务。多行一致性需应用层协调或使用协处理器(Coprocessor)。
扩展性HBase 水平扩展能力强,可轻松扩展至数千节点;关系型数据库垂直扩展为主,水平分片复杂。扩展时自动负载均衡由 HMaster 和 RegionServer 协作完成。
查询能力HBase 原生仅支持基于 RowKey 的点查和范围扫描,不支持 JOIN、GROUP BY 等;关系型数据库支持完整 SQL。复杂查询需结合 Hive、Spark 或 Phoenix 实现。
存储引擎基于 LSM-Tree(Log-Structured Merge-Tree),写入高效;关系型数据库多基于 B+Tree。写入先写 WAL 再写 MemStore,保证崩溃恢复。

1.3 HBase 的数据模型

概念名称说明注意事项
表(Table)逻辑数据容器,由行组成,行按 RowKey 字典序排序。表必须至少包含一个列族。
行键(RowKey)唯一标识一行的字节数组,决定数据物理存储位置和访问效率。RowKey 设计不当会导致热点问题(如时间戳前缀)。建议加盐或哈希。
列族(Column Family)表的顶层列分组,物理上存储在一起,需在建表时定义。列族名应简短(如 cf1),因每单元格都存储列族名,影响存储开销。
列限定符(Qualifier)列族下的具体列标识,无需预定义,可动态创建。Qualifier 可重复使用于不同行,且不同行可拥有不同 Qualifier。
时间戳(Timestamp)每个单元格值的版本标识,默认为写入时的系统时间(毫秒),也可显式指定。默认保留 1 个版本,可通过列族属性设置 VERSIONS 保留多个历史版本。
单元格(Cell){RowKey, Column Family, Qualifier, Timestamp} 唯一确定的数据项,存储二进制值。Cell 值无类型,均为字节数组(byte[]),应用层负责序列化/反序列化。
稀疏性空列不占用存储空间,适合存储稀疏数据(如用户行为日志中大量空字段)。与关系型数据库中 NULL 占用空间不同,HBase 对未写入的列视为不存在。

1.4 HBase 的架构组成

概念名称说明注意事项
Client提供访问 HBase 的接口,维护缓存(如 Region 位置信息),直接与 RegionServer 通信。Client 不经过 HMaster 读写数据,降低中心节点压力。
ZooKeeper协调服务,管理集群状态,存储 HBase 元数据(如 hbase:meta 表位置、Master 地址)。ZooKeeper 故障将导致 HBase 不可用,需高可用部署。
HMaster主节点,负责表管理(创建/删除/修改)、Region 分配、故障恢复、负载均衡等。HMaster 无单点故障(支持 standby),但不参与数据读写路径。
RegionServer工作节点,管理多个 Region,处理客户端读写请求,执行 Compaction 和 Split。每个 RegionServer 管理的 Region 数量受内存和磁盘限制。
Region表的水平分区,每个 Region 负责一段连续的 RowKey 范围,是分布式存储的基本单位。Region 默认大小 10GB,过大影响分裂和恢复速度。
HFileRegion 中列族数据的底层存储文件,基于 HDFS,采用块索引和布隆过滤器加速查询。HFile 是只读的,由 MemStore flush 生成。
MemStore写入缓冲区,每个列族在 Region 中有一个 MemStore,数据先写入内存再刷盘。MemStore 满(默认 128MB)或周期性触发 flush 到 HFile。
Write-Ahead Log (WAL)预写日志,记录所有写操作,用于 RegionServer 崩溃后数据恢复。WAL 默认开启,可针对特定表关闭以提升写性能(牺牲可靠性)。

第二章:HBase 环境搭建

2.1 依赖环境准备(Hadoop、ZooKeeper)

步骤名称操作细节注意事项
安装 Java JDK安装 JDK 8 或 JDK 11(HBase 2.x 推荐 JDK 8,3.x 支持 JDK 11),配置 JAVA_HOME必须使用 Oracle JDK 或 OpenJDK,不支持其他 JVM 实现。
配置 SSH 免密登录在单机或集群节点间配置 SSH 免密码登录(用于 Hadoop 和 HBase 启动脚本)。即使单机模式也建议配置 localhost 免密,避免启动警告。
安装 Hadoop下载并解压 Hadoop(建议 3.x 版本),配置 core-site.xmlhdfs-site.xml,格式化 NameNode 并启动 HDFS。HBase 依赖 HDFS 存储数据,不能使用本地文件系统(除单机模式外)。确保 Hadoop 已正常运行(jps 查看 DataNode/NameNode)。
安装 ZooKeeper可使用 HBase 自带的 ZooKeeper(测试用),或独立安装 ZooKeeper(生产推荐)。若使用外部 ZooKeeper,需在 hbase-site.xml 中指定 quorum 地址;若使用内置,HBase 会自动启动 zk 进程。
设置主机名与 hosts配置 /etc/hostname/etc/hosts,确保所有节点能通过主机名互相解析。主机名不能含下划线或大写字母,避免 DNS 解析失败。
关闭防火墙与 SELinux执行 systemctl stop firewalld(CentOS)或 ufw disable(Ubuntu),临时关闭安全策略。生产环境应配置白名单而非完全关闭,但初学可临时关闭以避免连接问题。

2.2 单机模式安装

步骤名称操作细节注意事项
下载 HBase从 Apache 官网下载 hbase-x.x.x-bin.tar.gz,解压至 /opt/hbase 或用户目录。选择与 Hadoop 版本兼容的 HBase 版本(如 HBase 2.4.x 对应 Hadoop 3.x)。
配置 hbase-env.sh设置 JAVA_HOME 路径,例如 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk必须显式设置,否则启动失败。
配置 hbase-site.xml设置属性:hbase.rootdir=file:///tmp/hbase-${user.name}hbase.cluster.distributed=false单机模式使用本地文件系统(file://),不依赖 HDFS。
启动 HBase执行 bin/start-hbase.sh,查看进程(jps 应出现 HMaster)。日志位于 logs/ 目录,若启动失败需检查日志。
进入 HBase Shell执行 bin/hbase shell,输入 list 验证是否正常。首次启动会自动创建 hbase:metahbase:namespace 表。
停止 HBase执行 bin/stop-hbase.sh强制 kill 可能导致数据损坏,应使用 stop 脚本。

2.3 伪分布式模式安装

步骤名称操作细节注意事项
确保 HDFS 已启动在同一台机器上先启动 Hadoop HDFS(start-dfs.sh),确保 NameNode 和 DataNode 运行。HBase 数据将写入 HDFS,路径如 hdfs://localhost:9000/hbase
修改 hbase-site.xml设置:hbase.cluster.distributed=truehbase.rootdir=hdfs://localhost:9000/hbasehbase.zookeeper.quorum=localhost必须将 hbase.rootdir 指向 HDFS 路径,端口需与 Hadoop core-site.xmlfs.defaultFS 一致。
配置 RegionServer默认已启用,无需额外配置;若需多 RegionServer,需配置 regionservers 文件。伪分布式通常只运行一个 RegionServer。
启动 HBase执行 bin/start-hbase.shjps 应出现 HMaster、HRegionServer、HQuorumPeer(若用内置 ZK)。若使用外部 ZooKeeper,需先启动 zkServer.sh
验证 Web UI访问 http://localhost:16010(HMaster Web UI)查看集群状态。HBase 2.x 默认 Web 端口为 16010,1.x 为 60010。
测试读写在 shell 中 create 'test', 'cf'put 'test', 'row1', 'cf:a', 'value1'scan 'test'确保 HDFS 有足够空间,且 HBase 用户对 HDFS /hbase 目录有写权限。

2.4 完全分布式模式部署要点

步骤名称操作细节注意事项
规划集群角色至少 3 节点:1 个 HMaster(可配 standby),多个 RegionServer,3 节点 ZooKeeper 集群。HMaster 可部署在 NameNode 节点,RegionServer 应部署在 DataNode 节点(数据本地性)。
同步配置文件hbase-site.xmlregionservershbase-env.sh 等配置文件分发到所有节点相同路径。所有节点 HBase 安装路径和配置必须一致。
配置 hbase-site.xml设置 hbase.rootdir=hdfs://namenode:9000/hbasehbase.zookeeper.quorum=zk1,zk2,zk3hbase.master=master-hosthbase.zookeeper.property.clientPort 默认 2181,若非默认需显式配置。
配置 regionservers 文件列出所有 RegionServer 主机名(每行一个),如 regionserver1regionserver2该文件决定哪些节点运行 HRegionServer 进程。
启动顺序1. 启动 HDFS;2. 启动 ZooKeeper 集群;3. 在 Master 节点执行 start-hbase.sh顺序不可颠倒,否则 HBase 无法连接依赖服务。
高可用配置(可选)配置 backup-masters 文件,列出备用 Master 主机名,实现 HMaster HA。需依赖 ZooKeeper 选举 Active Master。
监控与日志通过 Web UI(16010)监控 Region 分布、请求速率;日志集中收集(如 ELK)。RegionServer OOM 是常见问题,需合理设置 HBASE_HEAPSIZE(如 8G~16G)。
目录权限确保 HDFS 上 /hbase 目录属主为 hbase 用户(或启动用户),权限为 755。权限不足会导致 RegionServer 无法写 WAL 或 HFile。

第三章:HBase Shell 命令行基础

3.1 启动与退出 HBase Shell

命令名称语法用途代码示例注意事项
启动 Shellhbase shell进入 HBase 交互式命令行环境hbase shell需确保 HBase 服务已启动(start-hbase.sh),否则连接失败。
退出 Shellexitquit退出 HBase Shell 返回操作系统终端exit也可使用 Ctrl+D 快捷键退出。

3.2 表管理命令(create, list, describe, disable, drop 等)

命令名称语法用途代码示例注意事项
createcreate '表名', '列族1', '列族2', ...创建新表,必须指定至少一个列族create 'users', 'info', 'address'列族需在建表时定义,后续可 alter 添加,但不建议频繁修改。
listlist列出所有表名list返回表名列表,可用于脚本判断表是否存在。
describedescribe '表名'查看表的详细结构(列族、配置、Region 信息等)describe 'users'显示 COMPRESSION、VERSIONS、TTL 等列族属性。
existsexists '表名'检查表是否存在exists 'users'返回 true/false,常用于 Shell 脚本条件判断。
disabledisable '表名'禁用表(必须先禁用才能删除或修改结构)disable 'users'禁用后无法读写该表,操作会抛出 TableNotEnabledException
is_disabledis_disabled '表名'检查表是否处于禁用状态is_disabled 'users'返回 true 表示已禁用。
enableenable '表名'启用已禁用的表enable 'users'启用后恢复读写能力。
is_enabledis_enabled '表名'检查表是否已启用is_enabled 'users'返回 true 表示可用。
dropdrop '表名'删除表(必须先 disable)disable 'users'; drop 'users'删除不可逆,数据将从 HDFS 中清除(除非有快照)。
drop_alldrop_all '正则表达式'批量删除匹配正则的表(需先 disable)drop_all 'test.*'高危操作,慎用;需确认正则匹配范围。

3.3 数据写入命令(put)

命令名称语法用途代码示例注意事项
putput '表名', '行键', '列族:限定符', '值' [, 时间戳]向指定单元格写入数据put 'users', 'user1', 'info:name', 'Alice'值为字符串,内部以字节数组存储;若省略时间戳,使用系统当前毫秒时间。
put(带时间戳)put '表名', '行键', '列族:限定符', '值', 时间戳写入指定版本的数据put 'users', 'user1', 'info:name', 'Alice_v2', 1700000000000时间戳单位为毫秒,可用于手动控制版本。重复时间戳会覆盖原值。

3.4 数据读取命令(get, scan)

命令名称语法用途代码示例注意事项
getget '表名', '行键'获取某一行的所有列数据get 'users', 'user1'返回该行所有列族下所有列的最新版本。
get(指定列)get '表名', '行键', {COLUMN => '列族:限定符'}获取某一行指定列的数据get 'users', 'user1', {COLUMN => 'info:name'}可使用 COLUMNS(复数)指定多个列。
get(多版本)get '表名', '行键', {COLUMN => 'cf:q', VERSIONS => N}获取某列的最近 N 个版本get 'users', 'user1', {COLUMN => 'info:name', VERSIONS => 3}需表/列族已配置保留多版本(默认只保留 1 个)。
scanscan '表名'全表扫描(按 RowKey 顺序)scan 'users'大表慎用,可能引发 RegionServer OOM。
scan(范围)scan '表名', {STARTROW => '起始行', STOPROW => '结束行'}扫描指定 RowKey 范围(左闭右开)scan 'users', {STARTROW => 'user1', STOPROW => 'user3'}STOPROW 不包含自身。
scan(过滤列)scan '表名', {COLUMNS => ['cf1:q1', 'cf2:q2']}仅返回指定列scan 'users', {COLUMNS => ['info:name']}减少网络传输,提升性能。
scan(限制行数)scan '表名', {LIMIT => N}限制返回最多 N 行scan 'users', {LIMIT => 5}常用于调试或分页。

3.5 数据删除命令(delete, deleteall)

命令名称语法用途代码示例注意事项
deletedelete '表名', '行键', '列族:限定符' [, 时间戳]删除指定单元格的某个版本delete 'users', 'user1', 'info:name', 1700000000000若省略时间戳,删除最新版本;数据标记为”墓碑”,实际删除在 Compaction 时完成。
delete(最新版)delete '表名', '行键', '列族:限定符'删除该列的最新版本delete 'users', 'user1', 'info:name'同上,不指定时间戳即删最新。
deletealldeleteall '表名', '行键'删除整行所有列的所有版本deleteall 'users', 'user1'相当于对行内所有列执行 delete。
deleteall(指定列)deleteall '表名', '行键', '列族:限定符'删除某列所有版本deleteall 'users', 'user1', 'info:name'比多次 delete 更高效。

3.6 表结构修改命令(alter)

命令名称语法用途代码示例注意事项
alter(添加列族)alter '表名', '列族名'为表添加新列族alter 'users', 'contact'表必须处于 disabled 状态(HBase 2.x 起支持在线 add_column_family,但旧版本需 disable)。
alter(修改列族属性)alter '表名', {NAME => '列族', 属性 => 值}修改列族配置(如 VERSIONS、TTL)alter 'users', {NAME => 'info', VERSIONS => 5}需先 disable 表(除非使用 HBase 2.0+ 的在线 schema change)。
alter(删除列族)alter '表名', 'delete' => '列族名'删除列族(HBase 1.x 语法)alter 'users', 'delete' => 'old_cf'HBase 2.x 推荐使用 drop_column_family 命令。
alter(HBase 2.x 删除列族)alter '表名', 'drop_column_family' => '列族名'删除列族(新语法)alter 'users', 'drop_column_family' => 'old_cf'删除后,该列族所有数据将被标记删除,Compaction 后物理清除。
alter(生效变更)alter '表名', {...}, true在旧版本中,部分 alter 需加 true 参数触发执行alter 'users', {NAME => 'info', TTL => 86400}, trueHBase 2.x 多数操作自动生效,无需 true。

第四章:HBase 数据模型深入

4.1 行键(Row Key)设计原则

概念名称说明注意事项
唯一性RowKey 是表中每一行的唯一标识,由应用层生成,HBase 不提供自增 ID。必须保证全局唯一,否则会覆盖已有行。
字典序排序所有行按 RowKey 的字典序(byte-wise)物理存储,影响扫描效率和数据局部性。设计时应将高频查询字段前置(如 user_id + timestamp),避免全表扫描。
热点问题若 RowKey 具有单调递增性(如时间戳开头),会导致写入集中于单个 Region,形成热点。解决方案:加盐(prefix hashing)、反转时间戳、哈希分桶等。
长度控制RowKey 是二进制字节数组,建议控制在 10~100 字节以内。过长会增加存储开销(每个 Cell 都重复存储 RowKey)和网络传输负担。
可读性 vs 性能可使用组合字段(如 device_id#event_time)提升可读性,但需权衡解析成本。生产环境建议使用紧凑编码(如 Base64、Protobuf)而非明文字符串。
查询模式驱动设计RowKey 应围绕主要查询模式设计(点查、范围查、前缀匹配)。无法通过非 RowKey 字段高效查询,需借助二级索引(如 Coprocessor 或外部系统)。

4.2 列族(Column Family)与列限定符(Qualifier)

概念名称说明注意事项
列族(Column Family)表的顶层逻辑分组,物理上对应一个 Store(含 MemStore + StoreFiles)。列族数量应尽量少(通常 1~3 个),因每个列族独立存储,过多会增加 I/O 和内存开销。
列族预定义建表时必须显式声明列族,后续可通过 alter 添加,但不建议频繁变更。列族名应简短(如 cff1),因每个 Cell 都存储列族名,影响存储效率。
列限定符(Qualifier)列族下的具体列标识,无需预定义,可动态创建,由应用自由命名。Qualifier 可为任意字节数组(如 "name""1700000000000"),支持高维稀疏数据。
存储隔离不同列族的数据物理分离,可独立设置压缩算法、TTL、块大小等属性。高频访问列与低频列应分属不同列族,便于优化存储策略。
访问粒度读写操作以列族为单位加载(HFile 块缓存),即使只读一个 Qualifier 也会加载整个列族块。避免将无关列放入同一列族,防止”读放大”。
动态 schema同一表中不同行可拥有完全不同的 Qualifier 集合,体现 NoSQL 灵活性。应用需自行维护数据语义一致性,HBase 不校验列是否存在。

4.3 时间戳(Timestamp)与版本控制

概念名称说明注意事项
时间戳(Timestamp)每个 Cell 的版本标识,默认为写入时的系统时间(毫秒),也可由客户端显式指定。时间戳为 long 类型,单位毫秒;相同 RowKey+CF+Qualifier+TS 的写入会覆盖原值。
多版本支持HBase 默认保留 1 个版本,可通过列族属性 VERSIONS 设置保留 N 个历史版本。VERSIONS=5 表示保留最近 5 个不同时间戳的值。
版本查询get/scan 可通过 VERSIONS 参数获取多个历史版本。返回结果按时间戳降序排列(最新在前)。
手动指定时间戳客户端可在 put 时传入自定义时间戳,用于回填历史数据或实现逻辑版本。需确保时间戳唯一性,否则可能意外覆盖。
TTL(Time To Live)列族可设置 TTL(秒),超过 TTL 的 Cell 在 Compaction 时自动删除。TTL=86400 表示保留 1 天;设为 FOREVER(-1)则永不过期。
删除与版本delete 操作会写入”墓碑”标记,后续读取时过滤被删版本,Compaction 时物理清除。删除某版本后,仍可读取更早的有效版本(若存在)。

4.4 单元格(Cell)与稀疏存储特性

概念名称说明注意事项
单元格(Cell)数据存储的最小单位,由 {RowKey, Column Family, Qualifier, Timestamp} 唯一确定,值为 byte[]Cell 无数据类型,应用负责序列化(如 JSON、Avro、Thrift)。
稀疏性未写入的列不占用任何存储空间,适合存储大量空字段的宽表。与关系型数据库中 NULL 占用空间不同,HBase 对缺失列视为不存在。
存储结构Cell 在 HFile 中按 RowKey → CF → Qualifier → TS 排序存储,支持快速定位。LSM-Tree 结构使写入高效,但读取可能需合并多个 HFile。
值大小限制单个 Cell 值建议不超过 10MB,过大影响性能(如 BlockCache 效率、RPC 超时)。大对象(如图片)应存 HDFS/S3,HBase 仅存路径引用。
无模式约束同一 Qualifier 在不同行可存储不同类型数据(如一行存数字,另一行存字符串)。应用需自行保证数据一致性,HBase 不做类型检查。
多版本 Cell相同 RowKey+CF+Qualifier 可存在多个不同 Timestamp 的 Cell,构成版本链。读取时默认返回最新有效版本(未被删除且未过期)。

第五章:HBase Shell 高级操作

5.1 扫描过滤器(Filter)使用

命令名称语法用途代码示例注意事项
PrefixFilterscan '表名', {FILTER => "PrefixFilter('前缀')"}按 RowKey 前缀过滤scan 'logs', {FILTER => "PrefixFilter('202501')"}仅匹配 RowKey 以指定字符串开头的行;前缀需为字符串形式。
RowFilterscan '表名', {FILTER => "RowFilter(=, 'binary:行键值')"}按 RowKey 精确或比较过滤scan 'users', {FILTER => "RowFilter(=, 'binary:user123')"}支持 =, !=, >, >=, <, <=binary 表示字节比较,可替换为 regexstring 等。
QualifierFilterscan '表名', {FILTER => "QualifierFilter(=, 'binary:name')"}按列限定符过滤scan 'users', {FILTER => "QualifierFilter(=, 'binary:email')"}仅返回包含指定 Qualifier 的列;常与 ColumnPrefixFilter 结合使用。
ValueFilterscan '表名', {FILTER => "ValueFilter(=, 'binary:Alice')"}按单元格值过滤scan 'users', {FILTER => "ValueFilter(=, 'binary:Alice')"}性能较差,因需扫描所有 Cell 值;大表慎用。
SingleColumnValueFilterscan '表名', {FILTER => "SingleColumnValueFilter('cf','q',=,'binary:v')"}按某列值决定是否返回整行scan 'users', {FILTER => "SingleColumnValueFilter('info','status',=,'binary:active')"}若该列不存在,默认不返回行;可通过 filterIfMissing=>false 改变行为。
PageFilterscan '表名', {FILTER => "PageFilter(10)"}限制返回行数(分页)scan 'logs', {FILTER => "PageFilter(5)"}仅控制客户端接收行数,RegionServer 仍可能扫描更多数据。
SkipFilterscan '表名', {FILTER => "SkipFilter(ValueFilter(...))"}跳过满足子过滤器条件的行scan 't', {FILTER => "SkipFilter(ValueFilter(=,'binary:temp'))"}与 WhileMatchFilter 等组合使用可实现复杂逻辑。
多过滤器组合scan '表', {FILTER => "AND(过滤器1, 过滤器2)"}"OR(...)"逻辑组合多个过滤器scan 't', {FILTER => "AND(PrefixFilter('u'), ValueFilter(=,'binary:admin'))"}支持 AND、OR、NOT;注意括号匹配和引号转义。

5.2 计数与统计命令(count)

命令名称语法用途代码示例注意事项
countcount '表名' [, INTERVAL=>N, CACHE=>M]统计表中总行数count 'users'默认每 1000 行打印一次进度;大表执行慢,因需全表 scan。
count(带间隔)count '表名', {INTERVAL => 10000}每 N 行输出一次进度count 'logs', {INTERVAL => 50000}INTERVAL 控制日志频率,不影响结果。
count(带缓存)count '表名', {CACHE => 1000}设置 scanner 缓存行数count 'users', {CACHE => 2000}CACHE 越大,RPC 次数越少,但内存消耗增加;默认 1000。
手动估算(替代方案)使用 HBase Web UI 或 Region 信息估算快速获取近似行数生产环境大表应避免 count,可用采样或外部计数器替代。

5.3 快照管理(snapshot, clone_snapshot, restore_snapshot)

命令名称语法用途代码示例注意事项
snapshotsnapshot '表名', '快照名'为表创建快照(元数据+HFile 引用)snapshot 'users', 'users_backup_20250201'快照创建瞬间完成,不复制数据;依赖 HDFS 快照功能(需启用)。
list_snapshotslist_snapshots列出所有快照list_snapshots显示快照名、表名、创建时间、状态。
describe_snapshotdescribe_snapshot '快照名'查看快照详细信息describe_snapshot 'users_backup_20250201'包含 Region 列表、HFile 引用等。
clone_snapshotclone_snapshot '快照名', '新表名'从快照克隆出新表clone_snapshot 'users_backup_20250201', 'users_restored'新表独立于原表,可读写;不占用额外存储(HFile 共享)。
restore_snapshotrestore_snapshot '快照名'将原表恢复到快照状态disable 'users'; restore_snapshot 'users_backup_20250201'; enable 'users'必须先 disable 表;会覆盖当前表数据,不可逆。
delete_snapshotdelete_snapshot '快照名'删除快照(释放 HFile 引用)delete_snapshot 'users_backup_20250201'若快照被 clone 表引用,删除后 clone 表仍可访问数据(HDFS 引用计数机制)。

5.4 权限与安全命令(grant, revoke, user_permission)

注:以下命令需在 HBase 启用安全认证(如 Kerberos + ACL)后才生效。

命令名称语法用途代码示例注意事项
grantgrant '用户', '权限', '表名'授予用户对表的权限grant 'alice', 'RWXCA', 'users'权限字符:R=Read, W=Write, X=Execute, C=Create, A=Admin;可作用于命名空间(如 @default)。
revokerevoke '用户', '表名'撤销用户对表的所有权限revoke 'bob', 'logs'撤销后用户无法再访问该表(除非有全局权限)。
user_permissionuser_permission '表名'查看表的权限分配情况user_permission 'users'显示用户及其拥有的权限;若省略表名,列出所有表权限。
grant(列族级)grant '用户', '权限', '表', '列族'授予列族级细粒度权限grant 'charlie', 'RW', 'users', 'info'HBase 2.x 支持列族级 ACL,1.x 仅支持表级。
superuser配置 hbase.superuser 参数设置超级用户(绕过权限检查)hbase-site.xml 中设置 hbase.superuser=root,hbase超级用户可执行任何操作,需谨慎配置。
启用安全模式设置 hbase.security.authorization=true开启 HBase ACL 功能需在 hbase-site.xml 中配置并重启集群未启用时,grant/revoke 命令无效。

第六章:HBase Java API 编程

6.1 连接配置与 Connection 管理

方法/类名称语法用途代码示例注意事项
ConfigurationConfiguration conf = HBaseConfiguration.create();创建 HBase 客户端配置对象Configuration conf = HBaseConfiguration.create();必须设置 ZooKeeper 地址;若使用默认端口(2181),可省略 clientPort
设置 ZK 地址conf.set("hbase.zookeeper.quorum", "zk1,zk2");指定 ZooKeeper 集群地址conf.set("hbase.zookeeper.quorum", "localhost");
设置 ZK 端口conf.set("hbase.zookeeper.property.clientPort", "2181");指定 ZooKeeper 客户端端口
ConnectionConnection connection = ConnectionFactory.createConnection(conf);建立到 HBase 集群的连接(线程安全、重量级)Connection conn = ConnectionFactory.createConnection(conf);Connection 是共享资源,应在应用生命周期内复用,避免频繁创建/关闭。
close()connection.close();关闭连接并释放资源conn.close();应在应用退出或不再使用时调用;未关闭可能导致连接泄漏。
getAdmin()Admin admin = connection.getAdmin();获取 Admin 对象用于 DDL 操作(建表、删表等)Admin admin = conn.getAdmin();Admin 非线程安全,每次使用后应 close()
getTable()Table table = connection.getTable(TableName.valueOf("users"));获取 Table 对象用于 DML 操作Table table = conn.getTable(TableName.valueOf("users"));Table 是轻量级、线程安全的,可多线程共享;使用后应 close()

6.2 表创建与删除

方法/类名称语法用途代码示例注意事项
TableName.valueOf()TableName tableName = TableName.valueOf("表名");将字符串转换为 TableName 对象TableName tn = TableName.valueOf("logs");所有表操作需使用 TableName 类型。
TableDescriptorBuilderTableDescriptor td = TableDescriptorBuilder.newBuilder(tableName).build();构建表描述符TableDescriptor td = TableDescriptorBuilder.newBuilder(tn).build();需配合 ColumnFamilyDescriptorBuilder 使用。
ColumnFamilyDescriptorBuilderColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("cf")).build();定义列族属性(如 VERSIONS、TTL)ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder .newBuilder(Bytes.toBytes("info")) .setVersions(1, 5) .setTimeToLive(86400) .build();属性链式调用;必须指定列族名(byte[])。
createTable()admin.createTable(td);创建表admin.createTable(td);表必须包含至少一个列族;若表已存在,抛出 TableExistsException
deleteTable()admin.disableTable(tableName); admin.deleteTable(tableName);删除表(需先禁用)admin.disableTable(tn); admin.deleteTable(tn);必须先 disable,否则抛出 TableNotDisabledException
tableExists()boolean exists = admin.tableExists(tableName);检查表是否存在if (!admin.tableExists(tn)) { ... }用于安全创建表前判断。

6.3 Put/Get/Scan/Delete 操作

方法/类名称语法用途代码示例注意事项
PutPut put = new Put(Bytes.toBytes("row1")); put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("qual"), Bytes.toBytes("value"));构造写入操作Put p = new Put(Bytes.toBytes("user1")); p.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("Alice"));支持 addColumn(cf, qual, ts, value) 指定时间戳;值必须为 byte[]
put()table.put(put);执行单条写入table.put(p);自动 flush;也可批量提交(见 6.4)。
GetGet get = new Get(Bytes.toBytes("row1")); get.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("qual"));构造读取操作Get g = new Get(Bytes.toBytes("user1")); g.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));可设置 setMaxVersions(N) 获取多版本。
get()Result result = table.get(get); byte[] val = r.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));执行单行读取Result r = table.get(g); byte[] val = r.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));若行不存在,Result.isEmpty() 返回 true。
ScanScan scan = new Scan(); scan.withStartRow(Bytes.toBytes("a")); scan.withStopRow(Bytes.toBytes("z"));构造扫描操作Scan s = new Scan(); s.addColumn(Bytes.toBytes("info"), Bytes.toBytes("email"));支持 setFilter() 设置过滤器;stopRow 不包含自身。
getScanner()ResultScanner scanner = table.getScanner(scan); for (Result r : rs) { ... } rs.close();执行扫描并返回迭代器ResultScanner rs = table.getScanner(s); for (Result r : rs) { ... } rs.close();必须显式 close() ResultScanner,否则 RegionServer 资源泄漏。
DeleteDelete delete = new Delete(Bytes.toBytes("row1")); delete.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("qual"));构造删除操作Delete d = new Delete(Bytes.toBytes("user1")); d.addColumns(Bytes.toBytes("info"), Bytes.toBytes("name"));addColumn() 删除最新版本;addColumns() 删除所有版本。
delete()table.delete(delete);执行删除table.delete(d);支持批量删除(List)。

6.4 批量操作与缓存控制

方法/类名称语法用途代码示例注意事项
put(List)List puts = new ArrayList<>(); puts.add(put1); puts.add(put2); table.put(puts);批量写入多行List list = new ArrayList<>(); list.add(new Put(...)); table.put(list);比循环单条 put 更高效;自动分 region 提交。
delete(List)table.delete(deletes);批量删除List dels = ...; table.delete(dels);同上,支持批量。
setWriteBufferSize()table.setWriteBufferSize(128 * 1024 * 1024);设置客户端写缓冲区大小(字节)table.setWriteBufferSize(64 * 1024 * 1024);缓冲区满时自动 flush;仅对 AutoFlush=false 有效(旧 API)。
BufferedMutatorBufferedMutator mutator = connection.getBufferedMutator(tableName); mutator.mutate(put); mutator.flush();异步批量写入(新 API)BufferedMutator mutator = conn.getBufferedMutator(tn); mutator.mutate(put); mutator.close();自动批处理和重试;适合高吞吐写入场景。
setReadRpcTimeout()Get get = new Get(row); get.setReadRpcTimeout(5000);设置单次读 RPC 超时(毫秒)get.setReadRpcTimeout(10000);防止慢查询阻塞;全局超时可在配置中设置 hbase.rpc.timeout
setBatch()scan.setBatch(10);设置每次 RPC 返回的最大列数scan.setBatch(5);防止大行导致 OOM;与 setCaching() 区分(caching 控制行数)。

第七章:HBase 性能与运维

7.1 Region 分裂与合并机制

概念名称说明注意事项
Region 分裂(Split)当 Region 大小超过阈值(默认 10GB),HBase 自动将其一分为二,新 Region 由 HMaster 分配到其他 RegionServer,实现负载均衡。分裂过程不阻塞读写(HBase 2.x 支持”无缝分裂”);但频繁分裂会增加元数据负担和 Compaction 压力。
分裂触发条件hbase.hregion.max.filesize 控制(默认 10737418240 字节 = 10GB);也可手动执行 split '表名', 'splitKey'不建议将阈值设得太小(如 <1GB),否则 Region 数量爆炸;太大则影响恢复速度和负载均衡。
预分区(Pre-splitting)建表时通过 SPLITS 参数预先划分多个 Region,避免初期热点。例如:create 'logs', 'cf', {SPLITS => ['1000','2000','3000']}预分区键需按 RowKey 字典序分布;适用于已知 RowKey 范围的场景(如用户 ID 区间)。
Region 合并(Merge)手动将两个相邻 Region 合并为一个,减少小 Region 数量,降低管理开销。命令:merge_region 'ENCODED_REGION_A', 'ENCODED_REGION_B'合并不自动触发,需管理员干预;合并前需 disable 表(HBase 2.x 支持在线 merge,但需谨慎)。
Region 热点某个 Region 接收大量请求,导致单点性能瓶颈。常见于单调递增 RowKey(如时间戳开头)。解决方案:RowKey 加盐、哈希、反转时间戳;或使用 salting + 二级索引。
Region 定位Client 通过 ZooKeeper 获取 hbase:meta 表位置,再从 meta 表查目标 Region 地址,缓存后直连 RegionServer。meta 表本身也是一个 HBase 表,其 Region 永远不会分裂;若 meta 损坏,集群不可用。

7.2 Compaction 机制

概念名称说明注意事项
Minor Compaction合并少量小 HFile 为一个较大 HFile,不删除过期或被删除的数据(墓碑保留)。自动触发,频率高;减少文件数量,提升读性能。
Major Compaction合并所有 HFile 为一个,同时清理过期数据(TTL)、多版本超限数据、墓碑标记。默认 7 天一次(hbase.hregion.majorcompaction);I/O 和 CPU 开销大,生产环境常关闭自动 major,改为手动低峰期执行。
Compaction 触发条件MemStore flush 后 HFile 数量 ≥ hbase.hstore.compactionThreshold(默认 3);或 HFile 大小差异过大。可通过 hbase shell 执行 major_compact '表名' 手动触发。
墓碑(Tombstone)清理delete 操作写入墓碑标记,仅在 Major Compaction 时物理删除对应 Cell。若长期不执行 Major Compaction,存储空间无法释放,查询性能下降(需跳过墓碑)。
Off-peak Compaction在低峰期调度 Major Compaction,避免影响在线服务。需结合 cron 或 HBase 自带调度器(如通过 hbase-site.xml 配置窗口期)。
Compaction 策略支持 RatioBasedCompactionPolicy(默认)、ExploringCompactionPolicy 等,控制哪些 HFile 参与合并。可通过列族属性设置:alter 't', {NAME=>'cf', COMPACTION_POLICY_CLASS=>...}

7.3 常见 Shell 诊断命令(status, version, whoami)

命令名称语法用途代码示例注意事项
statusstatusstatus 'simple' / 'summary' / 'detailed'查看集群运行状态(RegionServer 数、请求速率、负载等)status 'detailed'simple 显示概要;detailed 显示每个 RegionServer 的 load、requests、regions。
versionversion显示 HBase、ZooKeeper、Hadoop 版本信息version用于排查版本兼容性问题(如 HBase 2.4 需 Hadoop 3.x)。
whoamiwhoami显示当前 Shell 用户身份(Kerberos 认证下显示 principal)whoami在启用安全认证时用于确认权限上下文。
balancerbalancer_switch true/false / balancer手动开关或触发 Region 负载均衡balancer_switch true; balancerbalancer 命令立即执行一次均衡;自动均衡由 HMaster 定期调度。
regioninfolocate_region '表名', '行键'查看某行所在的 Region 信息(编码、服务器地址)locate_region 'users', 'user100'用于定位热点或调试路由问题。
is_in_maintenance_modeis_in_maintenance_mode检查集群是否处于维护模式is_in_maintenance_mode维护模式下禁止自动均衡和分裂。

7.4 备份与恢复策略

策略名称说明注意事项
快照备份(Snapshot)使用 snapshot 命令创建表的只读快照,基于 HDFS 快照,几乎瞬时完成,不中断服务。最推荐的备份方式;支持 clone_snapshot 快速恢复为新表;依赖 HDFS 快照功能(需 dfs.allow.snapshots=true)。
Export/Import 工具使用 org.apache.hadoop.hbase.mapreduce.Export 将表导出为 HFile,再用 Import 导入。适合跨集群迁移;但导出过程需 scan 全表,对在线服务有压力。
CopyTable 工具通过 MapReduce 将表复制到同集群或远程集群。支持增量复制(指定 starttime/endtime);需开启 replication 或网络互通。
DistCp + HDFS 备份直接使用 Hadoop DistCp 复制 /hbase 目录到备份集群。高风险!必须在 HBase 停止状态下执行,否则 HFile 不一致;仅用于灾难恢复。
WAL 恢复RegionServer 崩溃后,HMaster 通过 WAL 重放未刷盘的写入,保证数据不丢失。WAL 必须开启(默认开启);若 WAL 损坏,可能丢失最近写入。
多级备份策略生产环境建议:每日快照 + 异地 DistCp 归档 + 监控快照有效性。快照不防人为 drop 表(drop 会删快照关联的 HFile);重要数据应定期 clone 快照为独立表归档。
恢复流程1. 从快照 restore_snapshot(覆盖原表);2. 或 clone_snapshot 为新表后 rename;3. 验证数据一致性。restore 前必须 disable 表;clone 方式更安全,可并行验证后再切换。