前言
HBase 是一个构建在 Hadoop HDFS 之上的分布式、面向列的 NoSQL 数据库。它是 Google Bigtable 的开源实现,具有高可靠性、高性能、可伸缩的特点,适合存储海量稀疏数据。本文将详细介绍 HBase 的基本概念、Shell 命令、Java API 以及常用操作。
一、HBase 核心概念
1.1 数据模型
概念
说明
Table(表)
HBase 中数据的逻辑组织单位
Row Key(行键)
表中每行数据的唯一标识,按字典序排序
Column Family(列族)
列的集合,必须在建表时预先定义
Column Qualifier(列限定符)
列族中的具体列,可以动态添加
Cell(单元格)
由行键、列族、列限定符、时间戳唯一确定的数据单元
Timestamp(时间戳)
每个 Cell 的版本标识,默认为写入时间
1.2 数据坐标
HBase 中定位一个数据需要四个维度:
复制代码
[Row Key, Column Family, Column Qualifier, Timestamp] -> Value
1.3 物理存储结构
复制代码
Table
└── Region (按 Row Key 范围划分)
└── Store (每个 Column Family 对应一个 Store)
├── MemStore (内存缓存)
└── StoreFile/HFile (磁盘文件)
二、HBase Shell 基础命令
2.1 连接与帮助
bash
复制代码
# 启动 HBase Shell
hbase shell
# 退出 HBase Shell
exit
quit
# 查看帮助
help
# 查看特定命令的帮助
help 'create'
help 'put'
help 'get'
# 查看命令组
help 'general'
help 'ddl'
help 'dml'
help 'namespace'
# 查看 HBase 状态
status
status 'simple'
status 'summary'
status 'detailed'
# 查看版本
version
# 查看当前用户
whoami
# 查看表列表
list
三、命名空间(Namespace)操作
命名空间类似于关系型数据库中的数据库概念,用于对表进行逻辑分组。
bash
复制代码
# 创建命名空间
create_namespace 'my_namespace'
# 创建命名空间并设置属性
create_namespace 'my_namespace', {'PROPERTY_NAME'=>'PROPERTY_VALUE'}
# 查看所有命名空间
list_namespace
# 查看命名空间详情
describe_namespace 'my_namespace'
# 查看命名空间下的表
list_namespace_tables 'my_namespace'
# 修改命名空间属性
alter_namespace 'my_namespace', {METHOD => 'set', 'PROPERTY_NAME' => 'PROPERTY_VALUE'}
# 删除命名空间属性
alter_namespace 'my_namespace', {METHOD => 'unset', NAME => 'PROPERTY_NAME'}
# 删除命名空间(必须为空)
drop_namespace 'my_namespace'
系统默认命名空间
命名空间
说明
hbase
系统内置表所在的命名空间
default
未指定命名空间时的默认命名空间
四、表(Table)DDL 操作
4.1 创建表
bash
复制代码
# 基本创建(单个列族)
create 'table_name', 'column_family'
# 创建多个列族
create 'table_name', 'cf1', 'cf2', 'cf3'
# 使用完整语法创建
create 'table_name', {NAME => 'cf1'}, {NAME => 'cf2'}
# 在指定命名空间创建表
create 'my_namespace:table_name', 'cf1'
# 创建表并设置列族属性
create 'table_name', {NAME => 'cf1', VERSIONS => 5}
# 设置多个列族属性
create 'table_name', {
NAME => 'cf1',
VERSIONS => 5,
TTL => 86400,
BLOCKCACHE => true,
COMPRESSION => 'SNAPPY'
}
# 创建预分区表
create 'table_name', 'cf1', SPLITS => ['10', '20', '30', '40']
# 使用分区文件创建
create 'table_name', 'cf1', SPLITS_FILE => '/path/to/splits.txt'
# 使用十六进制分区
create 'table_name', 'cf1', {NUMREGIONS => 16, SPLITALGO => 'HexStringSplit'}
# 使用均匀分区
create 'table_name', 'cf1', {NUMREGIONS => 10, SPLITALGO => 'UniformSplit'}
4.2 列族属性详解
属性
说明
默认值
NAME
列族名称
必填
VERSIONS
保留的版本数
1
MIN_VERSIONS
最小保留版本数
0
TTL
数据生存时间(秒)
FOREVER
BLOCKCACHE
是否启用块缓存
true
BLOCKSIZE
块大小(字节)
65536
COMPRESSION
压缩算法
NONE
BLOOMFILTER
布隆过滤器类型
ROW
REPLICATION_SCOPE
复制范围
0
IN_MEMORY
是否优先缓存在内存
false
DATA_BLOCK_ENCODING
数据块编码
NONE
4.3 压缩算法选项
bash
复制代码
# 可用的压缩算法
COMPRESSION => 'NONE' # 不压缩
COMPRESSION => 'GZ' # Gzip 压缩
COMPRESSION => 'SNAPPY' # Snappy 压缩(推荐)
COMPRESSION => 'LZO' # LZO 压缩
COMPRESSION => 'LZ4' # LZ4 压缩
COMPRESSION => 'ZSTD' # Zstandard 压缩
4.4 布隆过滤器选项
bash
复制代码
BLOOMFILTER => 'NONE' # 不使用
BLOOMFILTER => 'ROW' # 基于行键(默认)
BLOOMFILTER => 'ROWCOL' # 基于行键+列限定符
4.5 查看表信息
bash
复制代码
# 查看所有表
list
# 使用正则过滤表
list 'user.*'
list 'ns:.*'
# 查看表是否存在
exists 'table_name'
# 查看表结构
describe 'table_name'
desc 'table_name'
# 查看表的详细信息
describe 'table_name'
# 查看表的 Region 信息
list_regions 'table_name'
# 获取表的 Region 位置
locate_region 'table_name', 'row_key'
4.6 修改表
bash
复制代码
# 禁用表(修改前必须先禁用)
disable 'table_name'
# 检查表是否禁用
is_disabled 'table_name'
# 启用表
enable 'table_name'
# 检查表是否启用
is_enabled 'table_name'
# 添加列族
alter 'table_name', NAME => 'new_cf'
# 添加列族并设置属性
alter 'table_name', NAME => 'new_cf', VERSIONS => 3, TTL => 86400
# 修改列族属性
alter 'table_name', NAME => 'cf1', VERSIONS => 5
# 删除列族
alter 'table_name', NAME => 'cf1', METHOD => 'delete'
alter 'table_name', 'delete' => 'cf1'
# 修改表级属性
alter 'table_name', MAX_FILESIZE => '134217728'
alter 'table_name', READONLY => true
# 设置表的协处理器
alter 'table_name', 'coprocessor' => 'hdfs:///path/to/coprocessor.jar|com.example.MyCoprocessor|1001|'
# 移除协处理器
alter 'table_name', METHOD => 'table_att_unset', NAME => 'coprocessor$1'
# 同时修改多个列族
alter 'table_name', {NAME => 'cf1', VERSIONS => 5}, {NAME => 'cf2', TTL => 86400}
4.7 删除表
bash
复制代码
# 禁用表
disable 'table_name'
# 删除表
drop 'table_name'
# 批量禁用表(使用正则)
disable_all 'test.*'
# 批量删除表(使用正则)
drop_all 'test.*'
# 清空表数据(保留表结构)
truncate 'table_name'
# 保留分区的清空
truncate_preserve 'table_name'
五、数据 DML 操作
5.1 插入/更新数据(Put)
bash
复制代码
# 基本插入
put 'table_name', 'row_key', 'cf:qualifier', 'value'
# 插入并指定时间戳
put 'table_name', 'row_key', 'cf:qualifier', 'value', timestamp
# 插入带属性
put 'table_name', 'row_key', 'cf:qualifier', 'value', {ATTRIBUTES => {'attr1' => 'value1'}}
# 示例
put 'users', 'user001', 'info:name', 'John'
put 'users', 'user001', 'info:age', '25'
put 'users', 'user001', 'info:email', 'john@example.com'
put 'users', 'user001', 'contact:phone', '1234567890'
# 插入二进制数据
put 'table_name', 'row_key', 'cf:qualifier', "\x00\x01\x02\x03"
5.2 获取数据(Get)
bash
复制代码
# 获取整行数据
get 'table_name', 'row_key'
# 获取指定列族
get 'table_name', 'row_key', 'cf
get 'table_name', 'row_key', 'cf:qualifier'
# 获取多个列
get 'table_name', 'row_key', 'cf1:q1', 'cf2:q2'
# 获取指定列族的多个列
get 'table_name', 'row_key', {COLUMN => ['cf:q1', 'cf:q2']}
# 获取指定时间戳的数据
get 'table_name', 'row_key', {COLUMN => 'cf:qualifier', TIMESTAMP => 1234567890}
# 获取指定时间范围的数据
get 'table_name', 'row_key', {COLUMN => 'cf:qualifier', TIMERANGE => [1234567890, 1234567900]}
# 获取多个版本
get 'table_name', 'row_key', {COLUMN => 'cf:qualifier', VERSIONS => 5}
# 获取所有版本
get 'table_name用过滤器
get 'table_name', 'row_key', {FILTER => "ValueFilter(=, 'binary:value')"}
# 获取原始数据(包括删除标记)
get 'table_name', 'row_key', {RAW => true, VERSIONS => 10}
5.3 扫描数据(Scan)
bash
复制代码
# 扫描整表
scan 'table_name'
# 限制返回行数
scan 'table_name', {LIMIT => 10}
# 指定起始和结束行键
scan 'table_name', {STARTROW => 'row001', STOPROW => 'row100'}
# 包含结束行键(HBase 2.0+)
scan 'table_name', {STARTROW => 'row001', STOPROW => 'row100', INCLUSIVE_STOP_ROW => true}
# 扫描指定列族
scan 'table_name', {COLUMNS => 'cf'}
# 扫描指定列
scan 'table_name', {COLUMNS => ['cf:q1', 'cf:q2']}
# 扫描多个版本
scan 'table_name', {VERSIONS => 5}
# 指定时间范围
scan 'table_name', {TIMERANGE => [1234567890, 1234567900]}
# 反向扫描
scan 'table_name', {REVERSED => true}
# 设置缓存行数
scan 'table_name', {CACHE => 1000}
# 原始扫描(包括删除标记)
scan 'table_name', {RAW => true, VERSIONS => 10}
# 只返回行键
scan 'table_name', {FILTER => "KeyOnlyFilter()"}
# 只返回第一列
scan 'table_name', {FILTER => "FirstKeyOnlyFilter()"}
# 行键前缀过滤
scan 'table_name', {ROWPREFIXFILTER => 'user'}
# 使用过滤器
scan 'table_name', {FILTER => "PrefixFilter('row')"}
# 组合多个条件
scan 'table_name', {
STARTROW => 'row001',
STOPROW => 'row100',
COLUMNS => ['cf:q1', 'cf:q2'],
LIMIT => 100,
VERSIONS => 3,
FILTER => "ValueFilter(=, 'binary:value')"
}
5.4 删除数据(Delete)
bash
复制代码
# 删除指定列的最新版本
delete 'table_name', 'row_key', 'cf:qualifier'
# 删除指定列的指定版本
delete 'table_name', 'row_key', 'cf:qualifier', timestamp
# 删除整个列族
delete 'table_name', 'row_key', 'cf'
# 删除整行
deleteall 'table_name', 'row_key'
# 删除整行的指定列族
deleteall 'table_name', 'row_key', 'cf'
# 删除整行的指定列
deleteall 'table_name', 'row_key', 'cf:qualifier'
# 删除指定时间戳之前的所有版本
deleteall 'table_name', 'row_key', 'cf:qualifier', timestamp
5.5 计数器操作(Incr)
bash
复制代码
# 增加计数器
incr 'table_name', 'row_key', 'cf:qualifier', increment_value
# 增加 1
incr 'table_name', 'row_key', 'cf:qualifier', 1
# 减少(使用负数)
incr 'table_name', 'row_key', 'cf:qualifier', -1
# 获取计数器值
get_counter 'table_name', 'row_key', 'cf:qualifier'
5.6 追加操作(Append)
bash
复制代码
# 追加数据到现有值
append 'table_name', 'row_key', 'cf:qualifier', 'value_to_append'
六、过滤器(Filter)详解
6.1 比较过滤器
bash
复制代码
# 行键过滤器
scan 'table_name', {FILTER => "RowFilter(=, 'binary:row001')"}
scan 'table_name', {FILTER => "RowFilter(>=, 'binary:row001')"}
scan 'table_name', {FILTER => "RowFilter(=, 'substring:user')"}
scan 'table_name', {FILTER => "RowFilter(=, 'regexstring:user.*')"}
# 列族过滤器
scan 'table_name', {FILTER => "FamilyFilter(=, 'binary:cf1')"}
# 列限定符过滤器
scan 'table_name', {FILTER => "QualifierFilter(=, 'binary:name')"}
# 值过滤器
scan 'table_name', {FILTER => "ValueFilter(=, 'binary:value')"}
scan 'table_name', {FILTER => "ValueFilter(>=, 'binary:100')"}
scan 'table_name', {FILTER => "ValueFilter(=, 'substring:test')"}
# 时间戳过滤器
scan 'table_name', {FILTER => "TimestampsFilter(1234567890, 1234567891)"}
6.2 比较运算符
运算符
说明
=
等于
!=
不等于
>
大于
>=
大于等于
<
小于
<=
小于等于
6.3 比较器
比较器
说明
binary
精确匹配
binaryprefix
前缀匹配
substring
子串匹配
regexstring
正则匹配
6.4 专用过滤器
bash
复制代码
# 前缀过滤器
scan 'table_name', {FILTER => "PrefixFilter('user')"}
# 列前缀过滤器
scan 'table_name', {FILTER => "ColumnPrefixFilter('name')"}
# 多列前缀过滤器
scan 'table_name', {FILTER => "MultipleColumnPrefixFilter('name', 'age')"}
# 列范围过滤器
scan 'table_name', {FILTER => "ColumnRangeFilter('a', true, 'z', true)"}
# 单列值过滤器
scan 'table_name', {FILTER => "SingleColumnValueFilter('cf', 'age', >=, 'binary:18')"}
# 单列值排除过滤器
scan 'table_name', {FILTER => "SingleColumnValueExcludeFilter('cf', 'age', >=, 'binary:18')"}
# 页面过滤器(限制返回行数)
scan 'table_name', {FILTER => "PageFilter(10)"}
# 列分页过滤器
scan 'table_name', {FILTER => "ColumnPaginationFilter(5, 0)"}
# 列计数过滤器
scan 'table_name', {FILTER => "ColumnCountGetFilter(10)"}
# 首个键值过滤器
scan 'table_name', {FILTER => "FirstKeyOnlyFilter()"}
# 只返回键过滤器
scan 'table_name', {FILTER => "KeyOnlyFilter()"}
# 包含结束行过滤器
scan 'table_name', {FILTER => "InclusiveStopFilter('row100')"}
# 随机行过滤器
scan 'table_name', {FILTER => "RandomRowFilter(0.5)"}
# 依赖列过滤器
scan 'table_name', {FILTER => "DependentColumnFilter('cf', 'qualifier')"}
6.5 组合过滤器
bash
复制代码
# AND 组合
scan 'table_name', {FILTER => "PrefixFilter('user') AND ValueFilter(=, 'binary:active')"}
# OR 组合
scan 'table_name', {FILTER => "PrefixFilter('user') OR PrefixFilter('admin')"}
# SKIP 过滤器(跳过整行)
scan 'table_name', {FILTER => "SKIP ValueFilter(!=, 'binary:valid')"}
# WHILE 过滤器(遇到不匹配时停止)
scan 'table_name', {FILTER => "WHILE RowFilter(<=, 'binary:row100')"}
# 复杂组合
scan 'table_name', {
FILTER => "(PrefixFilter('user') AND SingleColumnValueFilter('cf', 'status', =, 'binary:active')) OR PrefixFilter('admin')"
}
七、Region 管理
7.1 Region 操作
bash
复制代码
# 查看表的 Region 列表
list_regions 'table_name'
# 手动分裂 Region
split 'table_name'
split 'table_name', 'split_key'
split 'region_name'
split 'region_name', 'split_key'
# 合并 Region
merge_region 'region_name_1', 'region_name_2'
merge_region 'region_name_1', 'region_name_2', true # 强制合并
# 移动 Region 到指定 RegionServer
move 'region_name', 'server_name'
# 关闭 Region
close_region 'region_name'
close_region 'region_name', 'server_name'
# 分配 Region
assign 'region_name'
# 取消分配 Region
unassign 'region_name'
# 平衡 Region
balance_switch true # 开启自动平衡
balance_switch false # 关闭自动平衡
balancer # 手动触发平衡
balancer_enabled # 查看平衡器状态
# 压缩 Region
compact 'table_name'
compact 'region_name'
compact 'table_name', 'cf'
# 主压缩
major_compact 'table_name'
major_compact 'region_name'
major_compact 'table_name', 'cf'
# 刷新 MemStore 到磁盘
flush 'table_name'
flush 'region_name'
7.2 Region 信息查询
bash
复制代码
# 获取 Region 位置
locate_region 'table_name', 'row_key'
# 查看 Region 状态
status 'detailed'
# 查看 hbase:meta 表
scan 'hbase:meta'
scan 'hbase:meta', {FILTER => "PrefixFilter('table_name')"}
八、快照(Snapshot)管理
bash
复制代码
# 创建快照
snapshot 'table_name', 'snapshot_name'
# 查看所有快照
list_snapshots
# 查看匹配的快照
list_snapshots 'snap.*'
# 查看快照详情
describe_snapshot 'snapshot_name'
# 从快照恢复表
disable 'table_name'
restore_snapshot 'snapshot_name'
enable 'table_name'
# 从快照克隆新表
clone_snapshot 'snapshot_name', 'new_table_name'
# 删除快照
delete_snapshot 'snapshot_name'
# 批量删除快照
delete_all_snapshot 'snap.*'
# 导出快照到 HDFS
# 在命令行执行
hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -snapshot snapshot_name -copy-to hdfs://destination/path
# 导入快照
# 在命令行执行
hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -snapshot snapshot_name -copy-from hdfs://source/path -copy-to hdfs://destination/path
九、安全与权限管理
9.1 用户权限
bash
复制代码
# 授予权限
grant 'user', 'RWXCA', 'table_name'
grant 'user', 'RW', 'table_name', 'cf'
grant 'user', 'R', 'table_name', 'cf', 'qualifier'
# 权限说明
# R - 读取
# W - 写入
# X - 执行
# C - 创建
# A - 管理
# 撤销权限
revoke 'user', 'table_name'
revoke 'user', 'table_name', 'cf'
# 查看用户权限
user_permission 'table_name'
# 授予命名空间权限
grant 'user', 'RWXCA', '@namespace'
# 授予全局权限
grant 'user', 'RWXCA'
9.2 可见性标签
bash
复制代码
# 添加标签
add_labels 'label1', 'label2'
# 设置用户标签
set_auths 'user', 'label1', 'label2'
# 获取用户标签
get_auths 'user'
# 清除用户标签
clear_auths 'user', 'label1'
# 插入带标签的数据
put'table_name', 'row_key', 'cf:qualifier', 'value', {VISIBILITY => 'label1'}
# 扫描带标签的数据
scan 'table_name', {AUTHORIZATIONS => ['label1', 'label2']}
十、Java API 使用
10.1 Maven 依赖
xml
复制代码
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.4.17</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-common</artifactId>
<version>2.4.17</version>
</dependency>
10.2 建立连接
java
复制代码
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
public class HBaseConnection {
private static Connection connection;
public static Connection getConnection() throws IOException {
if (connection == null || connection.isClosed()) {
Configuration config = HBaseConfiguration.create();
config.set("hbase.zookeeper.quorum", "zk1,zk2,zk3");
config.set("hbase.zookeeper.property.clientPort", "2181");
config.set("zookeeper.znode.parent", "/hbase");
connection = ConnectionFactory.createConnection(config);
}
return connection;
}
public static void closeConnection() throws IOException {
if (connection != null && !connection.isClosed()) {
connection.close();
}
}
}
10.3 DDL 操作
java
复制代码
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.io.compress.Compression;
public class HBaseDDL {
// 创建命名空间
public static void createNamespace(String namespace) throws IOException {
try (Admin admin = HBaseConnection.getConnection().getAdmin()) {
NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor
.create(namespace)
.addConfiguration("creator", "admin")
.build();
admin.createNamespace(namespaceDescriptor);
}
}
// 创建表
public static void createTable(String tableName, String... columnFamilies) throws IOException {
try (Admin admin = HBaseConnection.getConnection().getAdmin()) {
TableName tn = TableName.valueOf(tableName);
if (admin.tableExists(tn)) {
System.out.println("Table already exists");
return;
}
TableDescriptorBuilder tableBuilder = TableDescriptorBuilder.newBuilder(tn);
for (String cf : columnFamilies) {
ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder
.newBuilder(Bytes.toBytes(cf))
.setMaxVersions(3)
.setTimeToLive(86400)
.setCompressionType(Compression.Algorithm.SNAPPY)
.setBlockCacheEnabled(true)
.build();
tableBuilder.setColumnFamily(cfd);
}
admin.createTable(tableBuilder.build());
}
}
// 创建预分区表
public static void createTableWithSplits(String tableName, String cf, byte[][] splitKeys) throws IOException {
try (Admin admin = HBaseConnection.getConnection().getAdmin()) {
TableName tn = TableName.valueOf(tableName);
TableDescriptorBuilder tableBuilder = TableDescriptorBuilder.newBuilder(tn);
ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder
.newBuilder(Bytes.toBytes(cf))
.build();
tableBuilder.setColumnFamily(cfd);
admin.createTable(tableBuilder.build(), splitKeys);
}
}