
简介HBasehbase-2.4.9-bin.tar.gz是Apache Hadoop生态中面向列存储的分布式开源数据库适合大数据开发、后端存储与NoSQL方向的学习者及运维人员用于搭建非结构化数据的海量存储与实时读写环境。压缩包共2384个文件约270.36MB以1996个html文档、223个jar依赖包为主辅以sh启动脚本、xml与properties配置、css/js静态资源及少量图片字体完整覆盖运行、配置与文档查阅所需。目前已有5534人学习下载热度较高。资源基于Google Bigtable论文思想实现在HDFS之上提供类Bigtable能力采用列族模式而非传统行式关系模型适合非结构化数据存储场景。包内保留hbase-env、regionservers等配置样例与命令行脚本便于读者直接部署单机或集群环境对照官方文档理解RegionServer、Master等核心组件快速完成从环境搭建到数据读写的实践入门。1. HBase 2.4.9 单机与伪分布式落地从 tar.gz 解包到第一个读写请求手里拿到hbase-2.4.9-bin.tar.gz这个包很多人第一反应是直接tar -zxvf解压完就start-hbase.sh结果要么进程起不来要么起来了hbase shell卡在create上不动。HBase 不是那种解压即用的组件它依赖 JDK、依赖 ZooKeeper、依赖hbase-site.xml里那几个关键路径任何一个没对齐表现都是「进程在、服务不通」这种玄学状态。这篇笔记就围绕这个二进制包把单机模式和伪分布式模式两条路走通顺带把hbase安装与配置里最容易翻车的参数、hbase端口清单里必须放行的端口、以及后面pyspark写入hbase需要提前埋好的配置一次讲清楚。适合手上只有一台测试机、想先把 HBase 跑起来再谈集群的工程师也适合被hbase面试题里「HBase 读写流程」问懵、想动手验证一遍的人。2. 解包前后的环境对齐JDK、主机名与目录规划2.1 为什么 JDK 版本和 hostname 必须先定死HBase 2.4.9 编译时对标的是 JDK 8虽然 JDK 11 也能跑但hbase-2.4.9-bin.tar.gz里带的 Hadoop 依赖和部分反射调用在 JDK 17 上会直接抛InaccessibleObjectException。我一般会在解压前先确认三件事java -version输出是不是 1.8.x、hostname能不能被ping通、/etc/hosts里有没有把主机名映射到 127.0.0.1 或本机内网 IP。第三点最容易被忽略HBase 的 RegionServer 注册用的是主机名而不是 IP如果 hostname 解析不到Master 起来了也看不到 RegionServer。# 确认 JDK 版本必须是 1.8 java -version # 输出应类似java version 1.8.0_361 # 确认主机名可解析 hostname ping -c 1 $(hostname) # 如果 ping 不通往 /etc/hosts 补一行假设主机名是 hbase-test echo 127.0.0.1 hbase-test | sudo tee -a /etc/hosts上面这段的逻辑是java -version决定后面能不能用ping $(hostname)决定 HBase 内部通信能不能用/etc/hosts那行是补救措施。参数上唯一要注意的是主机名不要带下划线HBase 对主机名合法性有校验带下划线会在启动时报Invalid hostname。2.2 解压路径与软链接的取舍hbase-2.4.9-bin.tar.gz解压出来是hbase-2.4.9目录我习惯把它放到/opt或/data下然后做一个不带版本号的软链接hbase。这样做的好处是后面写HBASE_HOME、改配置文件、升级版本时不用动环境变量坏处是软链接指向要记清楚排查问题时readlink -f一下确认实际路径。# 解压到 /opt sudo tar -zxvf hbase-2.4.9-bin.tar.gz -C /opt # 建立软链接后续统一用 /opt/hbase sudo ln -s /opt/hbase-2.4.9 /opt/hbase # 确认目录结构 ls /opt/hbase # 应看到 bin conf hbase-webapps lib logs 等目录解压后先别急着改配置ls /opt/hbase/conf看一眼里面应该有hbase-env.sh、hbase-site.xml、regionservers三个核心文件。hbase-env.sh管环境变量hbase-site.xml管运行参数regionservers管 RegionServer 列表。伪分布式下regionservers里写本机主机名即可单机模式下这个文件其实用不到但留着不影响。2.3 环境变量与 HBASE_HOME 的写法环境变量这块HBASE_HOME指向软链接PATH里加上$HBASE_HOME/bin另外HBASE_LOG_DIR建议单独指一个目录不然日志默认落在$HBASE_HOME/logs下和安装目录混在一起清理时容易误删。hbase-env.sh里还要显式指定JAVA_HOME因为 HBase 启动脚本不会去读系统JAVA_HOME它只认这个文件里的值。# 编辑 /opt/hbase/conf/hbase-env.sh export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk export HBASE_LOG_DIR/data/hbase-logs export HBASE_MANAGES_ZKtrueHBASE_MANAGES_ZKtrue是伪分布式和单机模式下最省事的选项意思是让 HBase 自己拉起一个内置 ZooKeeper不用额外装。生产环境当然要独立 ZooKeeper但测试机上学hbase安装与配置这个开关能省掉一半的排错时间。注意这个变量在hbase-env.sh里默认是注释掉的要手动打开。3. hbase-site.xml 关键参数单机与伪分布式的分水岭3.1 单机模式的最小配置单机模式下 HBase 用本地文件系统不依赖 HDFS所有数据落在hbase.rootdir指定的本地目录。这个模式适合验证 API、跑单元测试但不适合压测因为本地文件系统没有副本机制也没有 HDFS 的吞吐优势。配置上只需要改一个hbase.rootdir其余保持默认。configuration property namehbase.rootdir/name valuefile:///data/hbase-data/value /property /configuration这里file:///三个斜杠不能少两个斜杠会被解析成相对路径启动时会在当前目录下建一个data目录后面找数据都找不到。/data/hbase-data这个目录不需要提前建HBase 启动时会自己创建但父目录/data要有写权限。3.2 伪分布式模式的四个必调参数伪分布式和单机的区别在于数据存 HDFS、ZooKeeper 独立管理、进程按 Master/RegionServer 角色分开。配置上要加四个属性少一个都会退化成单机或者起不来。configuration property namehbase.rootdir/name valuehdfs://localhost:9000/hbase/value /property property namehbase.cluster.distributed/name valuetrue/value /property property namehbase.zookeeper.quorum/name valuelocalhost/value /property property namehbase.zookeeper.property.dataDir/name value/data/zookeeper-data/value /property /configurationhbase.rootdir指向 HDFS 的 NameNode 地址端口要和core-site.xml里fs.defaultFS一致常见做法是 9000 或 8020。hbase.cluster.distributed设为 true 才会以分布式模式启动否则即使配了 HDFS 地址也走本地。hbase.zookeeper.quorum写 localhost 表示用本机 ZooKeeper配合前面HBASE_MANAGES_ZKtrue就是内置的。hbase.zookeeper.property.dataDir是 ZooKeeper 快照目录默认在/tmp下重启机器就丢必须改到持久化路径。3.3 端口清单与防火墙放行HBase 用到的端口不少伪分布式下至少涉及这几个HMaster 的 RPC 端口 16000、Web UI 端口 16010RegionServer 的 RPC 端口 16020、Web UI 端口 16030ZooKeeper 客户端端口 2181。如果开了防火墙这些端口要放行否则hbase shell连不上 Master报Connection refused。组件端口用途HMaster16000RPC 通信HMaster16010Web UIRegionServer16020RPC 通信RegionServer16030Web UIZooKeeper2181客户端连接# 以 firewalld 为例放行上述端口 sudo firewall-cmd --permanent --add-port16000/tcp sudo firewall-cmd --permanent --add-port16010/tcp sudo firewall-cmd --permanent --add-port16020/tcp sudo firewall-cmd --permanent --add-port16030/tcp sudo firewall-cmd --permanent --add-port2181/tcp sudo firewall-cmd --reload放行后可以用telnet localhost 16010验证 Web UI 端口通不通通的话会看到 HTML 响应头。这一步在云主机上尤其重要安全组和系统防火墙是两层只放一层等于没放。3.4 启动顺序与进程验证配置改完启动顺序是先确认 HDFS 已启动伪分布式依赖再start-hbase.sh。启动脚本会依次拉起 ZooKeeper、Master、RegionServer日志分别落在$HBASE_LOG_DIR下。启动后jps应该看到HMaster、HRegionServer、HQuorumPeer三个进程。# 确认 HDFS 已启动 jps | grep -E NameNode|DataNode # 启动 HBase /opt/hbase/bin/start-hbase.sh # 验证进程 jps | grep -E HMaster|HRegionServer|HQuorumPeer如果jps只看到HMaster没有HRegionServer八成是regionservers文件里主机名写错或者 hostname 解析有问题。如果三个进程都没有去看$HBASE_LOG_DIR/hbase-*-master-*.log最常见的报错是java.net.BindException说明端口被占lsof -i:16000查一下谁占的。4. 第一个读写请求hbase shell 与 Java API 双路径4.1 hbase shell 建表与写入进程起来后hbase shell是最快的验证方式。建表时要注意列族名和表名都是区分大小写的create test, cf里的cf是列族后面所有列都挂在列族下。写入用put读取用get和scan这几个命令在hbase面试题里出现频率极高但真正动手敲一遍和背答案完全是两回事。# 进入 shell /opt/hbase/bin/hbase shell # 建表指定列族 cf create test, cf # 写入一行数据rowkey 为 row1 put test, row1, cf:name, hbase-test # 读取 get test, row1 # 扫描全表 scan testput的第三个参数cf:name里cf是列族name是列限定符两者用冒号分隔。get返回的结果里会带时间戳这是 HBase 多版本特性的体现默认保留一个版本可以通过alter调整。scan不加限制会扫全表数据量大时加LIMIT或STARTROW/STOPROW。4.2 Java API 写入的最小可运行代码shell 验证完下一步是用 Java API 确认客户端依赖没问题。HBase 客户端依赖hbase-client和hbase-common两个 jar版本要和服务端一致2.4.9 的客户端连 2.4.x 服务端没问题连 2.3.x 可能报VersionMismatch。import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.*; public class HBaseDemo { public static void main(String[] args) throws Exception { // 加载 hbase-site.xmlclasspath 里要有 conf 目录 Configuration conf HBaseConfiguration.create(); // 显式指定 ZooKeeper 地址避免读不到配置 conf.set(hbase.zookeeper.quorum, localhost); conf.set(hbase.zookeeper.property.clientPort, 2181); try (Connection conn ConnectionFactory.createConnection(conf); Table table conn.getTable(TableName.valueOf(test))) { // 构造 Putrowkey 为 row2 Put put new Put(row2.getBytes()); put.addColumn(cf.getBytes(), name.getBytes(), java-api.getBytes()); table.put(put); // Get 验证 Get get new Get(row2.getBytes()); Result result table.get(get); System.out.println(new String(result.getValue(cf.getBytes(), name.getBytes()))); } } }这段代码的关键点是HBaseConfiguration.create()会去 classpath 找hbase-site.xml如果找不到就用默认值默认 ZooKeeper 地址是 localhost:2181恰好和伪分布式一致所以能跑通。但生产环境必须把hbase-site.xml打进 classpath否则连错集群都不知道。Connection是重量级对象要复用不要每次操作都新建Table是轻量级的可以随用随取。4.3 pyspark 写入 HBase 的前置配置pyspark写入hbase是热词里出现频率很高的场景核心依赖hbase-spark这个 connector。2.4.9 对应的 connector 版本是hbase-spark-2.4.9需要在spark-submit时通过--jars引入同时把hbase-site.xml放到 Spark 的 classpath 里。写入时用HBaseContext.bulkPut比逐条put快一个数量级因为走的是 RegionServer 的批量接口。from pyspark import SparkContext from pyspark.sql import SparkSession spark SparkSession.builder \ .appName(pyspark-hbase) \ .getOrCreate() # 假设 df 是要写入的 DataFrame包含 rowkey 和 value 两列 def write_to_hbase(iterator): import happybase conn happybase.Connection(localhost, port9090) table conn.table(test) for row in iterator: table.put(row[rowkey], {cf:name: row[value]}) df.foreachPartition(write_to_hbase)这里用的是happybase走 Thrift 接口需要额外启动hbase thrift start默认端口 9090。另一种方式是直接用hbase-spark的HBaseContext不依赖 Thrift但需要 Scala 环境。两种方式各有取舍Thrift 方式对 Python 友好但多一层网络开销HBaseContext性能好但配置复杂。测试阶段我一般先用 Thrift 跑通逻辑再换HBaseContext压性能。5. 避坑与排查那些让 HBase 起不来的细节5.1 现象start-hbase.sh 后 jps 没有 HMaster原因通常是hbase-env.sh里JAVA_HOME没配或配错启动脚本找不到 java 命令进程静默退出。解决方法是echo $JAVA_HOME确认路径存在然后bash -x /opt/hbase/bin/start-hbase.sh看执行到哪一步断的。另一个可能是HBASE_LOG_DIR目录没有写权限日志写不进去进程也会退。5.2 现象hbase shell 卡在 create 不动这是典型的 ZooKeeper 连接问题。hbase.zookeeper.quorum配的地址和实际 ZooKeeper 监听地址不一致或者 2181 端口被防火墙挡了。先在 Master 节点telnet localhost 2181确认端口通再看hbase-site.xml里 quorum 是不是写成了 IP 而 ZooKeeper 只监听主机名。HBASE_MANAGES_ZKtrue时 ZooKeeper 由 HBase 拉起如果这个开关没打开又没独立装 ZooKeepershell 就会一直重试。5.3 现象RegionServer 启动后马上挂掉看$HBASE_LOG_DIR/hbase-*-regionserver-*.log常见报错是hbase.rootdir指向的 HDFS 路径没权限。HBase 启动用户要对/hbase目录有写权限hdfs dfs -chmod 777 /hbase能临时解决但生产环境要按用户授权。另一个原因是hbase.zookeeper.property.dataDir指向的目录不存在且父目录没权限ZooKeeper 起不来RegionServer 跟着挂。5.4 现象Java API 报 NoClassDefFoundError客户端 jar 没打全hbase-client依赖hbase-common、hbase-protocol、hbase-shaded-*一系列包手动加 jar 很容易漏。用 Maven 的话直接依赖hbase-client2.4.9传递依赖会自动拉齐。如果用的是hbase-shaded-client注意它把部分类重命名了和普通客户端不能混用。5.5 现象pyspark 写入报 Thrift 连接超时happybase.Connection默认连 localhost:9090如果 Thrift 服务没启动或者端口不对就会超时。先hbase thrift start确认服务在再netstat -tlnp | grep 9090看监听地址。如果 Spark 是集群模式localhost要换成 Thrift 服务所在节点的实际 IP否则 executor 连的是自己那台机器。6. 进阶技巧用 hbase pe 和 UI 验证读写性能跑通基本读写后怎么确认这套 HBase 的性能边界我一般用hbase pe这个自带工具它能模拟读写负载输出吞吐和延迟。命令格式是hbase pe mode opts常用的是--nomapred单机模式、--rows指定行数、--size指定每行大小。# 写 100 万行每行 100 字节10 个线程 /opt/hbase/bin/hbase pe --nomapred --rows1000000 --size100 --threads10 randomWrite # 顺序读 /opt/hbase/bin/hbase pe --nomapred --rows1000000 --size100 --threads10 sequentialReadrandomWrite测的是随机写吞吐sequentialRead测顺序读两者结果差异能反映 rowkey 设计是否合理。如果随机写吞吐远低于顺序写说明 rowkey 分布不均热点集中在少数 Region。这个工具的好处是不依赖外部压测框架装完 HBase 就能用适合快速摸底。另一个验证手段是 Web UI。Master 的 16010 端口能看到 RegionServer 列表、表列表、请求数RegionServer 的 16030 端口能看到 Region 分布、StoreFile 大小、MemStore 占用。我习惯在压测时开着 16030 页面刷新观察 MemStore 是否频繁 flush如果 flush 过于频繁说明hbase.hregion.memstore.flush.size设小了默认 128MB测试环境可以调到 256MB 减少 flush 次数。参数默认值测试环境建议作用hbase.hregion.memstore.flush.size128MB256MB控制 MemStore 刷写阈值hbase.regionserver.handler.count3060RPC 处理线程数hbase.hregion.max.filesize10GB5GBRegion 分裂阈值最后说个我自己的习惯每次改完hbase-site.xml先stop-hbase.sh再start-hbase.sh不要用restart脚本因为部分参数不支持热加载restart 有时会残留旧进程导致新配置不生效。改配置前cp hbase-site.xml hbase-site.xml.bak翻车了能快速回滚。这套流程在测试机上跑通后再往集群迁移时把hbase.rootdir换成 HDFS 集群地址、hbase.zookeeper.quorum换成独立 ZooKeeper 列表其余配置基本可以照搬。希望帮到你。本文还有配套的精品资源点击获取