中文使用手册¶
中文 README · English documentation · 场景示例 / Cookbook
本手册面向首次接入和准备迁移的使用者。README 提供快速开始;这里解释数据如何组织、怎样连接、不同操作的返回值,以及实际接入时容易踩到的边界。文档描述当前仓库实现,不代表 Apache HBase 或 Java Client 的全部能力。
按任务查找¶
| 你要做什么 | 对应文档 |
|---|---|
| 安装、第一次读写 | 本页;详细安装入门 |
| 设计行键、存中文或 JSON | 本页;数据模型与编码 |
| 连接远程或 Docker 集群 | 本页;配置与连接生命周期 |
| 前缀查询、条件过滤、分页 | 可执行场景示例、高级用法 |
| 批量导入、计数、条件修改 | 可执行场景示例、API 参考 |
| 建表、改列族、快照管理 | 管理指南 |
| 接口存在但行为不符合预期 | 当前限制、故障排查 |
| 从 Java/Thrift/HappyBase 迁移 | 迁移检查表、HappyBase 迁移 |
| 测性能或参与开发 | 性能指南、开发环境、测试指南 |
| 维护示例、理解 PyPI 文档入口 | 文档维护 |
英文专题页包含更多接口细节;Cookbook 每个场景带中英文标题、前提条件和断言,可直接对应实际业务需求。
1. 安装:直接 pip 即可¶
客户不需要克隆仓库、启动 Docker 或创建 venv 才能安装:
venv 是可选的依赖隔离方式,不是必需步骤。如果使用系统管理的 Python,环境本身可能限制直接安装;可以选择已有应用环境或虚拟环境。安装会自动带上 kazoo 和 protobuf。
需要修改源码时,再在源码目录使用:
建议使用 Python 3.10+,项目当前验证环境为 Python 3.11 / HBase 2.6.1。能成功 import 只代表包已安装,不代表能够访问集群或全部功能已验证。
2. 连接的不是 Thrift¶
客户端先访问 ZooKeeper,再连接它返回的 Master 和 RegionServer 地址。因此,Python 进程必须能解析并访问这些主机名和端口,只转发 ZooKeeper 的 2181 端口通常不够。
import os
from hbasedriver.client.client import Client
from hbasedriver.hbase_constants import HConstants
config = {
HConstants.ZOOKEEPER_QUORUM: os.getenv("HBASE_ZK", "127.0.0.1:2181"),
}
这里由示例程序读取环境变量,再交给 Client;驱动不会自动读取 HBASE_ZK。
- 在本项目
hbase_dev内:hbase-zk:2181。 - 在本机访问本机 HBase:通常为
127.0.0.1:2181,还要确保广播地址可达。 - 远程集群:使用管理员提供的
host:port,多个地址以英文逗号分隔。 - 当前启动路径按默认
/hbaseznode 和简单认证实现,不能宣称已完整支持自定义 znode、Kerberos/SASL/TLS 或 Java 式自动故障恢复。
3. 先理解字节串与表结构¶
例如 default:users:
default是命名空间,users是表名。b"user:000001"是行键,按字节顺序排列。b"cf"是建表时定义的列族。b"name"是列限定符,写入时可以增加,不需要先定义每个列名。- 值由应用编码,例如
"张三".encode("utf-8")。
行键中数字的字符串排序不同于数值排序:b"10" < b"2"。固定宽度的非负整数编码可保持指定范围内的顺序,例如 f"{42:06d}".encode("ascii")。键格式应在写入前确定;变更格式意味着迁移已有数据。
Row.kv 是 {列族: {列限定符: 值}},不是 HappyBase 的扁平字典。不存在的行返回 None;不存在的列返回 None;b"" 是实际存在的空值,不能混为一谈。
4. 读写中文与 JSON¶
前提:已存在且启用 default:users 表,包含 cf 列族。此示例写入数据并保留,应用到真实表之前请更换示例行键或使用临时表。
import json
import os
from hbasedriver.client.client import Client
from hbasedriver.hbase_constants import HConstants
from hbasedriver.operations.get import Get
from hbasedriver.operations.put import Put
config = {HConstants.ZOOKEEPER_QUORUM: os.getenv("HBASE_ZK", "127.0.0.1:2181")}
with Client(config) as client:
with client.get_table(b"default", b"users") as table:
profile = {"name": "张三", "active": True}
table.put(
Put(b"user:000001")
.add_column(b"cf", b"name", profile["name"].encode("utf-8"))
.add_column(
b"cf", b"profile",
json.dumps(profile, ensure_ascii=False).encode("utf-8"),
)
)
row = table.get(Get(b"user:000001"))
if row is not None:
value = row.get(b"cf", b"profile")
if value is not None:
print(json.loads(value.decode("utf-8")))
HBase 不会自动按 JSON 字段过滤。需要独立查询的业务字段,应单独存为 qualifier,再用相应过滤器。
5. 扫描、过滤与分页¶
以下片段假定已经打开带有 cf 的 table:
from hbasedriver.filter import PrefixFilter
from hbasedriver.operations.scan import Scan
scan = (
Scan(start_row=b"user:")
.with_end_row(b"user;", inclusive=False)
.add_family(b"cf")
.set_filter(PrefixFilter(b"user:"))
)
with table.scan(scan) as scanner:
rows = scanner.next_batch(100)
for row in rows:
print(row.rowkey, row.kv)
这段代码读取至多 100 行后关闭 scanner,不是遍历整个表。当前 set_limit() 没有在扫描路径中形成全局行数限制,不能用它代替这里的读取上限。
分页使用 table.scan_page(scan, page_size),返回 (rows, resume_key)。下页通过 scan.with_start_row(resume_key, inclusive=False) 排除上一页最后一行,保留同样的过滤器和结束边界;直到返回空 rows 才结束。非空的最后一页仍可能带 resume_key。
注意:
- Scan 构造器的起止边界默认都包含;需要半开区间时显式设置结束边界不包含。
- 不支持在构造器传
include_start_row=False。 Scan.add_column()当前有序列化缺陷,可按列族扫描并结合 QualifierFilter。- 组合过滤器使用
FilterList(operator=FilterList.Operator.MUST_PASS_ALL, filters=[...])。 - SingleColumnValueFilter 的
filter_if_missing和latest_version_only是构造参数。 - 分页不是并发写入下的一致性快照;反向、多 Region 以及分裂/迁移恢复需要额外验证。
完整过滤和分页循环见场景示例。
6. 批量操作与缓冲写入¶
BatchGet 必须先构造,再增加列,不能链式赋值:
from hbasedriver.operations.batch import BatchGet
reads = BatchGet([b"user:000001", b"user:000002"])
reads.add_column(b"cf", b"name")
by_key = table.batch_get(reads)
for key, row in by_key.items():
print(key, None if row is None else row.get(b"cf", b"name"))
返回值是以行键为索引的字典。需要保持请求顺序或重复行键时,保留原始输入列表。BatchPut、BatchGet、Batch 和 BufferedMutator 当前底层仍逐条请求,不等同于批量 RPC、Bulk Load 或跨行事务。
显式管理 Table 所有权的缓冲写入:
from hbasedriver.client.buffered_mutator import BufferedMutator, BufferedMutatorParams
from hbasedriver.operations.put import Put
params = BufferedMutatorParams()
params.write_buffer_size = 1024 * 1024
params.write_buffer_periodic_flush = 0
with BufferedMutator(table, params) as mutator:
mutator.mutate(Put(b"import:001").add_column(b"cf", b"value", b"saved"))
mutator.flush()
Params 构造器不接收关键字参数;通过属性设置。周期 flush 单位为毫秒,0 表示关闭后台定时线程。关闭 mutator 不会关闭调用方的 Table。
mutate() 返回不等于数据已写入。flush 失败可能留下部分成功,待发送缓冲也不保证保留,必须在上游保存可恢复的输入,不能把缓冲器当持久化队列。
7. 原子操作的边界¶
- Increment:服务端递增;计数器存储为有符号 8 字节大端整数,不要用
b"0"初始化。 - CheckAndPut:同一行满足条件才写入;
None检查不存在,b""检查已有空值。 - Append:追加字节;重复执行会重复追加。
- RowMutations:同一行的操作组合;不是跨行事务。
- 超时可能发生在服务端已经执行之后,不能盲目重试计数/追加。
table.increment()只返回一个解码后的整数;如果依赖返回值,建议一次只操作一个计数器。
场景示例包含成功与条件不成立两条路径的断言。示例中的 claim 仅展示条件写入,不是带租约和 fencing token 的完整分布式锁。
8. 建表、删除与管理¶
建表的关键类型如下;此片段只构造对象,不操作集群:
from hbasedriver.common.table_name import TableName
from hbasedriver.operations.column_family_builder import ColumnFamilyDescriptorBuilder
name = TableName.value_of(b"default", b"users")
family = ColumnFamilyDescriptorBuilder(b"cf").build()
然后由已打开的 Admin 调用 admin.create_table(name, [family])。TableName 需要两个参数,builder 返回 protobuf 列族 schema,不存在可直接导入的 ColumnFamilyDescriptor。
删除需要先禁用表,且必须确认表归当前操作所有。不要在“表已存在则跳过创建”的示例末尾无条件删除那个表。admin.table_exists() 还会把异常转换成 False,False 不足以证明集群正常或表可安全重建。
truncate 当前是删除再重建,不保留完整表元数据和分区边界;快照恢复或克隆返回过程 ID,不代表已经完成。不要在普通文档验证中执行生产表删除、快照恢复或全局 balancer 修改。
9. 验证与故障定位¶
先将完整示例教程中的代码保存为本地 docs_quickstart.py,不要提交这个临时文件,再使用本仓库的 Docker 环境:
docker compose up -d
docker compose exec -T dev python docs_quickstart.py
docker compose exec -T dev python -m pytest test/test_batch_operations.py -v
docker compose stop
dev 对应 hbase_dev,不是其他项目的容器。完整示例创建唯一的 docs_demo_* 表并清理。Cookbook 的 8 个场景在准备阶段已直接运行验证;本次只发布文档和配置,不提交本地 Python 文档测试脚本,也不更新根目录的旧版示例。普通上下文片段不代表每段都独立执行,详细范围见验证说明。
排查顺序:确认 Python 导入路径 → ZooKeeper 地址 → 广播主机名可达性 → 表是否启用/列族存在 → API 参数及返回值 → 当前实现限制。错误报告保留必要栈信息,删除密码、令牌和客户数据,不要上传完整环境变量或 exports 文件。
10. 文档和发布版本¶
正式文档网站随 main 分支的文档更新自动构建和发布。英文 README 顶部有中文入口,PyPI 1.1.1 的项目说明和 Documentation 链接已纳入新的文档入口;旧版本的 PyPI 页面不会自动变化。
网站使用 MkDocs 和 GitHub Pages,提供导航、全文搜索、代码复制及深浅色切换。顶部有中文手册入口,但不是所有英文专题都已翻译。网站目前跟随 main,不是每个 PyPI 版本的独立文档快照。1.1.1 仅更新文档与包元数据,Python 源码与 1.1.0 一致;客户仍可直接 pip 安装,无需安装文档构建工具。
开始生产接入前,请读完当前限制:接口“有这个方法”与“所有参数都有端到端实现”是两回事。