HBase 2.5.16 单机部署
在业务系统中引入 HBase 之后,运维同学大概都遇到过这样几个场景:本地要跑一个验证环境、客户现场要演示一套系统、或者内网隔离环境需要离线装一套集群。这时候不装 Hadoop、不搭三节点,直接用**单机模式(Standalone)**把 HBase 跑起来,是最省事的选择。
本文以 HBase 2.5.16 + JDK 8 + Phoenix 5.3.2 在 CentOS Stream 9 上的实际部署过程为主线,先完整走一遍部署流程,再补充三类最容易出问题的注意事项:hosts 主机名解析、数据目录规划、远程访问端口开放。
第一部分 · 完整部署流程
1. 环境版本说明
HBase 与 Phoenix 的耦合很紧,Phoenix 是按 HBase 的小版本单独编译发布的,随便配一个上去,轻则功能异常,重则 RegionServer 直接挂掉。官方给出的支持矩阵:
| Phoenix 版本 | 支持的 HBase 版本 | 说明 |
|---|---|---|
| 4.16.1 | 1.3 / 1.4 / 1.5 / 1.6 | HBase 1.x 线 |
| 5.1.3 | 2.1 / 2.2 / 2.3 / 2.4 / 2.5 | 兼容范围最广 |
| 5.2.2 | 2.4 / 2.5 / 2.6 | --- |
| 5.3.2 | 2.5 / 2.6 | 本文采用 |
环境清单:
- 操作系统:CentOS Stream 9
- JDK:jdk-8u503(1.8.0_503)
- HBase:2.5.16
- Phoenix:5.3.2(包名 phoenix-hbase-2.5-5.3.2)
- 部署模式:Standalone(单机,独立 ZooKeeper + 本地文件系统)
- 主机名别名:hbase-server(192.168.16.2)
【注意】CentOS Stream 9 / RHEL 9 / Rocky 9 默认自带的是 JDK 11 或 17,而 HBase 2.5.16 官方支持 JDK 8 与 JDK 11 。直接用系统自带的 JDK 17 启动,大概率抛
UnsupportedClassVersionError。因此必须单独装一份 JDK 8,并在 hbase-env.sh 中显式指定。
2. 下载与解压
以下路径均以 /home 为基准。离线环境请在有外网的机器上下载好对应的包,再上传到服务器。
2.1 JDK 8
bash
tar -zxvf jdk-8u503-linux-x64.tar.gz
解压后目录为 /home/jdk1.8.0_503,后续 hbase-env.sh 中的 JAVA_HOME 要与它保持一致。
2.2 HBase 2.5.16
bash
# 方式一:官方主下载站
wget https://downloads.apache.org/hbase/2.5.16/hbase-2.5.16-bin.tar.gz
# 方式二:归档站(离线或镜像同步时更稳)
wget https://archive.apache.org/dist/hbase/2.5.16/hbase-2.5.16-bin.tar.gz
tar -zxvf hbase-2.5.16-bin.tar.gz
2.3 Phoenix 5.3.2
bash
wget https://archive.apache.org/dist/phoenix/phoenix-5.3.2/phoenix-hbase-2.5-5.3.2-bin.tar.gz
tar -zxvf phoenix-hbase-2.5-5.3.2-bin.tar.gz
# 把 Phoenix 服务端 jar 放进 HBase 的 lib 目录
cp phoenix-hbase-2.5-5.3.2-bin/phoenix-server-hbase-2.5-5.3.2.jar $HBASE_HOME/lib/
【注意】复制 jar 到
$HBASE_HOME/lib/之后,需要重启 HBase 才生效。漏了这步的表现是:hbase shell 能用,但 Phoenix 建表时报NoClassDefFoundError或找不到协处理器。
【提示】HBase 的压缩包按 Hadoop 版本区分:hbase-2.5.16-bin.tar.gz是内置 Hadoop 2 的通用版,单机本地文件系统模式下用它就够了。只有生产环境要跑在 Hadoop 3 上时,才需要下载hbase-2.5.16-hadoop3-bin.tar.gz。
3. 配置环境变量
bash
# 系统级环境变量
echo 'export HBASE_HOME=/home/hbase-2.5.16' > /etc/profile.d/hbase.sh
echo 'export PATH=$PATH:$HBASE_HOME/bin' >> /etc/profile.d/hbase.sh
source /etc/profile.d/hbase.sh
然后编辑 $HBASE_HOME/conf/hbase-env.sh:
bash
export JAVA_HOME=/home/jdk1.8.0_503
export HBASE_MANAGES_ZK=true
export HBASE_PID_DIR=/home/hbase-2.5.16/pids
export HBASE_LOG_DIR=/home/hbase-2.5.16/logs
# 内存配置:HBase 默认堆只有 1G,本地开发容易 OOM
export HBASE_HEAPSIZE=4G
export HBASE_MASTER_OPTS="-Xmx2G -XX:+UseG1GC"
export HBASE_REGIONSERVER_OPTS="-Xmx2G -XX:+UseG1GC"
# 跳过 Hadoop 依赖的 classpath 查找,启动能快十几秒
export HBASE_DISABLE_HADOOP_CLASSPATH_LOOKUP=y
| 配置项 | 作用 |
|---|---|
JAVA_HOME |
指定 JDK 路径,必须显式设置,不要依赖系统默认的 java |
HBASE_MANAGES_ZK=true |
单机模式的关键开关,开启后由 HMaster 自己管理内嵌 ZooKeeper |
HBASE_PID_DIR |
进程 PID 文件存放目录,需提前创建且可写 |
HBASE_LOG_DIR |
各进程日志目录,排障时第一时间看这里 |
HBASE_HEAPSIZE |
单机模式整体堆内存。机器只有 4GB 时设 1G~2G 即可 |
4. 配置 hbase-site.xml
xml
<configuration>
<!-- ========== 允许远程访问的关键:绑定所有网卡 ========== -->
<property><name>hbase.master.ipc.address</name><value>0.0.0.0</value></property>
<property><name>hbase.regionserver.ipc.address</name><value>0.0.0.0</value></property>
<property><name>hbase.master.info.bindAddress</name><value>0.0.0.0</value></property>
<property><name>hbase.zookeeper.property.clientPortAddress</name><value>0.0.0.0</value></property>
<!-- ========== 单机模式:使用本地文件系统 ========== -->
<property><name>hbase.cluster.distributed</name><value>false</value></property>
<property><name>hbase.rootdir</name><value>file:///home/hbase-2.5.16/data</value></property>
<property><name>hbase.tmp.dir</name><value>/home/hbase-2.5.16/tmp</value></property>
<property><name>hbase.zookeeper.property.dataDir</name><value>/home/hbase-2.5.16/zookeeper</value></property>
<property><name>hbase.zookeeper.quorum</name><value>hbase-server:2181</value></property>
<!-- ========== Phoenix 相关 ========== -->
<property><name>phoenix.schema.isNamespaceMappingEnabled</name><value>true</value></property>
<property><name>phoenix.schema.mapSystemTablesToNamespace</name><value>true</value></property>
</configuration>
| 配置项 | 说明 |
|---|---|
hbase.*.ipc.address |
RPC 监听地址。默认只绑 127.0.0.1,改成 0.0.0.0 才对外部署可达 |
hbase.cluster.distributed |
单机模式的开关。设为 true 会去找 regionservers 列表并等待集群上线 |
hbase.rootdir |
file:// 前缀表示落在本地磁盘而非 HDFS,这是单机模式不装 Hadoop 的前提 |
hbase.zookeeper.quorum |
ZK 地址。这里填主机名别名,与 hosts 配置呼应 |
phoenix.schema.* |
让 Phoenix 支持 HBase 的 namespace 功能,建表后不可更改 |
5. 创建数据目录
HBase 启动时不会自动创建 rootdir、tmpdir、ZooKeeper 数据目录,目录不存在会直接抛 Cannot create directory 而启动失败。所以这一步必须在启动前做完。
bash
mkdir -p /home/hbase-2.5.16/{data,tmp,zookeeper,pids,logs}
# 建议用独立的运行用户,避免权限问题
useradd -r -m hbase
chown -R hbase:hbase /home/hbase-2.5.16
chmod -R 750 /home/hbase-2.5.16/{data,tmp,zookeeper,pids,logs}
| 目录 | 存放内容 | 容量与增长 |
|---|---|---|
data/ |
核心数据区:HFile、WAL 预写日志 | 唯一会无限增长的目录,务必单独规划 |
tmp/ |
compaction、split 的临时工作区 | 建议给到 data 目录一半以上的容量 |
zookeeper/ |
ZK 快照、事务日志、myid 节点标识 | 很小,几百 MB 完全够用 |
pids/ |
各 Java 进程 PID 文件 | 几乎不占空间 |
logs/ |
HMaster / HRegionServer / HQuorumPeer 日志 | 会滚动增长,注意别把系统盘塞满 |
6. 配置 hosts
这一步直接决定了远程客户端能不能连上,必须在启动 HBase 之前配好。
bash
vi /etc/hosts
# IP 必须是这台机器真实的内网 IP,不能写 127.0.0.1
192.168.16.2 hbase-server
配完之后验证一下解析结果是否正确:
bash
getent hosts hbase-server # 应输出 192.168.16.2,而不是 127.0.0.1
7. 开放防火墙端口
单机模式下需要对外开放的端口如下,核心是前三个:
| 端口 | 组件 | 用途 | 必要性 |
|---|---|---|---|
| 2181 | ZooKeeper | 客户端连接 ZK 获取元数据;Phoenix JDBC 也走这个端口 | 必需 |
| 16000 | HMaster RPC | 建表、改表、获取 Region 路由 | 必需 |
| 16020 | RegionServer RPC | 真正的读写数据都走这个端口 | 必需 |
| 16010 | Master Web UI | http://hbase-server:16010,查看集群状态 | 建议 |
| 16030 | RegionServer Web UI | http://hbase-server:16030,排查慢请求 | 建议 |
| 9090 | Thrift Server | 仅在启动 Thrift 服务时需要 | 按需 |
| 8765 | Phoenix Query Server | 使用 Phoenix Thin Driver 时需要(默认未启动) | 按需 |
bash
firewall-cmd --permanent --zone=public --add-port=2181/tcp
firewall-cmd --permanent --zone=public --add-port=16000/tcp
firewall-cmd --permanent --zone=public --add-port=16020/tcp
firewall-cmd --permanent --zone=public --add-port=16010/tcp
firewall-cmd --permanent --zone=public --add-port=16030/tcp
firewall-cmd --reload
firewall-cmd --list-ports
8. 启动与验证
bash
$HBASE_HOME/bin/start-hbase.sh
# 单机模式下应该看到三个进程
jps
# 期望输出:HMaster、HRegionServer、HQuorumPeer
【提示】刚启动完立刻验证,往往会看到 "Master is initializing"------这是正常的,RegionServer 需要几十秒完成初始化和 Region 分配。等待 1 分钟后再检查即可。
命令行验证
bash
$HBASE_HOME/bin/hbase shell
hbase> status
# 期望:1 active master, 0 backup masters, 1 servers, 0 dead
hbase> create 'demo:t_user', {NAME =>'p1', VERSIONS => 3}
hbase> put 'demo:t_user', 'r1', 'p1:name', 'zhangsan'
hbase> scan 'demo:t_user'
hbase> describe 'demo:t_user'
hbase> disable 'demo:t_user'
hbase> drop 'demo:t_user'
用 demo: 这样的带命名空间前缀,可以顺便验证 Phoenix 的 namespace 配置是否生效。
Web UI 验证
在客户端机器 的 hosts 里加上同样的映射 192.168.16.2 hbase-server,然后浏览器访问:
- http://hbase-server:16010 (Master Web UI)
- http://hbase-server:16030 (RegionServer Web UI)
打开 Master UI 后重点看三处:Master 状态是否 active 、Servers 列表里 RegionServer 的 HostName 是否是正确的 IP (若显示 localhost 或 127.0.0.1,说明 hosts 配错了)、Tables 页签能否看到刚建的表。
停止服务
bash
$HBASE_HOME/bin/stop-hbase.sh
jps
9. DBeaver 连接 Phoenix
HBase 本身没有 JDBC 驱动,日常查数据靠 Phoenix 转接。配置思路很简单:驱动用 Phoenix 客户端 jar,地址填 ZooKeeper 的 host:2181。
| 配置项 | 填写内容 |
|---|---|
| 数据库类型 | 新建连接 → Apache HBase(或自定义 JDBC 连接) |
| 驱动 jar | phoenix-client-hbase-2.5-5.3.2.jar(已含 HBase 依赖) |
| 驱动类 | org.apache.phoenix.jdbc.PhoenixDriver |
| Host / Port | hbase-server / 2181 |
| Database / Schema | 留空 |
| 用户名 / 密码 | 留空(单机模式无认证) |
| JDBC URL | jdbc:phoenix:hbase-server:2181 |
| 连接属性 | phoenix.schema.isNamespaceMappingEnabled=true phoenix.schema.mapSystemTablesToNamespace=true |
连接成功后用 SQL 验证:
sql
CREATE TABLE IF NOT EXISTS demo.t_user (
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR,
age INTEGER,
ts TIMESTAMP
);
UPSERT INTO demo.t_user VALUES (1, 'zhangsan', 28, SYSTIMESTAMP());
UPSERT INTO demo.t_user VALUES (2, 'lisi', 32, SYSTIMESTAMP());
SELECT * FROM demo.t_user;
如果命令行的 sqlline 能查、DBeaver 连不上,那问题基本不在 HBase,而在 DBeaver 侧的 jar 依赖或驱动类选择上,可以用命令行做对照:
bash
./bin/sqlline.py hbase-server:2181
第二部分 · 注意事项
10. hosts 相关的六个坑
hosts 是整个部署中最容易出错、也最容易被忽略的一步。它的原理决定了三个现象:
客户端
↓ ① 连接 ZooKeeper(2181)
从 ZooKeeper 里读到"Master 地址"和"RegionServer 地址"
↓ ② 用这些地址去连 Master / RegionServer
真正读写数据
关键在第② 步:ZooKeeper 里存的地址,是 HBase 启动时通过主机名反向解析出来的 IP 。如果启动时 hbase-server 被解析成了 127.0.0.1,注册进 ZooKeeper 的就是 localhost:16020,别的机器拿到这个地址去连自己本机,自然就是 Connection refused。
坑 01 映射到 127.0.0.1 或 localhost------远程访问失败的头号根因,必须写真实的内网 IP
坑 02 只配了服务端,忘了客户端------对方机器 hosts 里没有这个别名,同样连不上
坑 03 改完 hosts 没重启 HBase------注册进 ZK 的是启动那一刻的解析结果,不会自动更新
坑 04 误以为 0.0.0.0 能解决一切------0.0.0.0 只管绑定,解析的事它管不了
坑 05 systemd 启动读不到环境变量------手工能起、服务化起不来,需在 unit 里显式声明
坑 06 多网卡机器注册了不可达地址------建议加一条 hbase.regionserver.hostname 显式指定
排查顺序:先用 getent hosts hbase-server 确认解析,再看 Master UI 里 RegionServer 的 HostName 显示的是什么,最后才怀疑防火墙。三步能把大部分问题定位清楚。
bash
hostname -f # 应与 hosts 中的别名一致
getent hosts hbase-server # 应输出真实内网 IP
getent hosts $(hostname -f) # 系统 hostname 本身也要能解析
ping -c 2 hbase-server
【提示】如果这台机器需要被公网访问,出于安全考虑可以不设
0.0.0.0,直接把这几个地址改成具体内网 IP(如192.168.16.2),从配置层面就只暴露内网。另外,别忘了时钟同步------ZooKeeper 对节点间时钟偏差敏感,建议用chronyd把偏差控制在 30 秒内,否则会出现会话超时、RegionServer 反复上下线。
11. 数据目录规划要点
要点一:把会增长的数据目录和系统盘分开。 默认放在 /home 下的问题是它与系统盘共享空间,一旦数据写满,最坏的情况是连 ssh 都连不上。挂一块独立磁盘是最省心的做法:
bash
/sbin/fdisk /dev/sdb # 分区
mkfs.xfs /dev/sdb1
mount /dev/sdb1 /home/hbase-2.5.16/data
echo '/dev/sdb1 /home/hbase-2.5.16/data xfs defaults,nofail 0 0' >> /etc/fstab
df -h /home/hbase-2.5.16/data
要点二:不要用 root 跑 HBase。 用 root 跑过一次测试、之后再切换到 hbase 用户启动,是最常见的"第二次就起不来"的原因:root 创建的文件属主是 root,hbase 用户无权写入。
要点三:不要把 data 目录放在 NFS 上。 单机文件系统模式下 HBase 依赖本地文件锁和 mmap,NFS 上的锁语义不可靠,容易出现写入异常甚至数据损坏。
要点四:备份必须先停服务。 单机模式没有副本机制,data 目录就是全部,拷到不一致的中间状态就失去意义了。
bash
$HBASE_HOME/bin/stop-hbase.sh
tar -zcvf hbase-data-$(date +%F).tar.gz -C /home/hbase-2.5.16 data zookeeper
# 干净重置环境:停服务后直接删 data 和 zookeeper 再重建,比逐个删表干净
rm -rf /home/hbase-2.5.16/{data,zookeeper} && mkdir -p /home/hbase-2.5.16/{data,zookeeper}
【注意】
hbase.rootdir的路径属于没有回头路的配置------改了路径等于换了一个库,旧数据不会自动迁移。建议第一次部署时就想清楚,并写进部署文档,后续所有环境统一照做。
12. 端口开放与安全
服务器上 telnet 通、浏览器打不开 Web UI,绝大多数情况下都是防火墙拦掉了。但把 firewalld 配好之后连不上,通常还剩两道"隐形墙":
隐形墙 01 SELinux enforcing 模式下会拦进程绑定端口。用 getenforce 查看,测试环境可临时 setenforce 0 验证
隐形墙 02 云服务器安全组 独立于服务器防火墙的上一道门,必须在云控制台里也放通相同端口,最容易被完全遗忘
如果这套环境只在一个内网段内使用,没必要把 2181、16000、16020 对所有来源开放。用 rich 规则限定来源网段更稳妥:
bash
for P in 2181 16000 16020 16010 16030; do
firewall-cmd --permanent --zone=public \
--add-rich-rule="rule family='ipv4' source address='192.168.16.0/24' port port='${P}' protocol='tcp' accept"
done
firewall-cmd --reload
firewall-cmd --list-rich-rules
验证命令:
bash
# 服务器上:确认服务真的在监听(而不是只在 localhost 上监听)
ss -tunlp | grep -E '2181|16000|16020|16010|16030'
# 客户端上
telnet hbase-server 2181
curl -I http://hbase-server:16010
echo srvr | nc hbase-server 2181
【提示】看
ss输出时留意绑定地址:127.0.0.1:16020说明还只监听本地,远程一定连不上;应该是*:16020或0.0.0.0:16020才表示对外开放。
13. 常见问题排查速查表
| 现象 | 原因与处理 |
|---|---|
Connection refused: localhost/127.0.0.1:16020 |
hosts 映射错误。检查是否映射到 127.0.0.1;改完 hosts 后重启 HBase |
Could not find any master |
jps 是否有 HMaster;看 logs/ 下 hbase-hmaster 日志首段报错 |
Master is initializing |
多半是正常等待。超过 2 分钟不恢复则查 data 目录权限、磁盘空间与时钟同步 |
Cannot create directory |
data / tmp / zookeeper 目录没建或当前用户无写权限 |
Address already in use |
端口被占。`ss -tunlp |
UnsupportedClassVersionError |
JDK 版本不对。确认 hbase-env.sh 的 JAVA_HOME 指向 JDK 8/11 |
OutOfMemoryError |
堆内存过小。调 HBASE_HEAPSIZE 或 HBASE_REGIONSERVER_OPTS |
| Phoenix 报找不到协处理器 | server jar 未放进 $HBASE_HOME/lib/,放入后重启 HBase |
| telnet 通但浏览器打不开 | 检查 SELinux 与云安全组是否放通 |
| RegionServer 反复上下线 | 时钟不同步导致 ZK 会话超时,用 chronyd 校时后重启 |
DBeaver 报 NoSuchMethodError |
驱动目录里混了多个版本 jar,清空后只保留一个版本 |
14. 单机模式的局限
部署完成后,有几条局限需要提前知道,避免误用:
- 无高可用:Master / RegionServer / ZooKeeper 全在同一台机器上,机器一挂服务就全停,进程挂了不会自动重启
- 无副本:数据只存一份,磁盘坏了就是数据没了,别拿它跑真实业务
- 单 RegionServer:所有读写压力集中在一个节点上,无法验证多节点下的数据分布与负载均衡逻辑
- 性能非生产级:适合开发、测试、演示,不要拿它做任何性能压测的基准依据
- 无认证:单机模式默认不开启 Kerberos,任何能连上端口的人都能读写全部数据
- 无容灾:单机文件系统不提供副本机制,data 目录就是全部,务必按前面说的方式做好备份
日常巡检三件事
bash
# 1. 进程是否齐全
jps | grep -E 'HMaster|HRegionServer|HQuorumPeer'
# 2. 集群是否健康(1 active master, 1 servers, 0 dead)
echo "status" | $HBASE_HOME/bin/hbase shell -n
# 3. 磁盘水位(data 目录剩余低于 30% 建议告警)
df -h | grep hbase
卸载清理
bash
$HBASE_HOME/bin/stop-hbase.sh
rm -rf /home/hbase-2.5.16 /home/jdk1.8.0_503 /home/phoenix-hbase-2.5-5.3.2-bin
rm -f /etc/profile.d/hbase.sh
# 同步清理防火墙规则
firewall-cmd --permanent --zone=public --remove-port=2181/tcp
firewall-cmd --permanent --zone=public --remove-port=16000-16030/tcp
firewall-cmd --reload
写在最后
HBase 单机部署本身并不复杂,真正的门槛在细节上。把最容易翻车的几个地方提前处理好,后面会顺很多:
- hosts ------ 别映射到 127.0.0.1,改完要重启 HBase,客户端也要配
- 数据目录 ------ 提前创建、大目录单独挂盘、别用 root 跑、别放 NFS 上
- 端口开放 ------ 2181 / 16000 / 16020 是刚需,别忘了 SELinux 和云安全组
- Phoenix ------ server jar 放进 lib 后记得重启;两个 namespace 属性首次部署就要定死
其中 hbase.rootdir 的路径 和 Phoenix 的两个 namespace 属性 属于"决定了就没有回头路"的配置,建议第一次部署时就想清楚、定下来写进部署文档,后面所有环境统一照做。