基于 Hadoop 伪分布式搭建 Hbase
上面我们已经完成了在Hyper-V中运行Ubuntu以及安装Hadoop,可以看我前面两篇文章:
现在在之前步骤的基础上,继续安装一波 Hbase 数据库
下载解压 Hbase
下载二进制文件
这里要根据大家之前安装的 Hadoop 来挑选对应的 Hbase 版本。具体的版本之间的对应关系,可以看下面的 Apache 官方文档:
由于我安装的是 Hadoop3.3 版本,所以要安装 Hbase 2.3.x 版本,和之前的 Hadoop 一样,我们可以从镜像站下载:
在终端直接运行命令:
hadoop@huxiaofan-ubuntu:/usr/local$ sudo wget https://downloads.apache.org/hbase/2.3.2/hbase-2.3.2-bin.tar.gz
接下来只需要一步解压,Hbase 就可以像 Hadoop 一样开箱即用了。
hadoop@huxiaofan-ubuntu:/usr/local$ sudo tar -zxf hbase-2.3.2-bin.tar.gz
hadoop@huxiaofan-ubuntu:/usr/local$ sudo mv hbase-2.3.2 hbase
经过这一步操作,Hbase 已经被安装到了 /usr/local/hbase 下面了。
但此时需要注意的是,由于是使用 sudo 来进行解压的,所以解压得到的文件所有者并不是 hadoop 用户,会为我们后面的运行带来一定的问题。所以现在还需要修改下整个 hbase 目录的权限。
修改前的权限情况
hadoop@huxiaofan-ubuntu:/usr/local$ sudo chown -R hadoop:hadoop hbase
修修改用户和用户组后
进一步的安装配置
配置 path 变量(可选)
PATH 环境变量用来指定命令的搜索路径。如果待运行的程序不在当前目录,操作系统便可以去依次搜索PATH变量变量中记录的目录,如果在这些目录中找到待运行的程序,操作系统便可以运行。
声明方法:
PATH=$PAHT:<PATH 1>:<PATH 2>:<PATH 3>: …… :< PATH n >
export PATH
可以自己在 <PATH 1>:<PATH 2>:<PATH 3>
加上指定的路径,中间用冒号隔开。
可以利用 echo $PATH
查看当前当前系统PATH路径
现在我们修改 path 使之全局生效。这里我们不仅配置 Hbase 的环境变量,也同时配置 Hadoop 的变量。而我们要做的很简单,只需要将 sbin 或者 bin 这些二进制文件的路径添加到 path 里即可。
hadoop@huxiaofan-ubuntu:/usr/local$ sudo vim /etc/profile
在下面追加如下内容,(已有的不要重复追加):
# JAVA_HOME
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
# HADOOP BIN
export PATH=$PATH:/usr/local/hadoop/sbin:/usr/local/hadoop/bin:/usr/local/hbase/bin
运行命令 source /etc/profile
来让我们新配置的变量立刻生效:
hadoop@huxiaofan-ubuntu:/usr/local$ source /etc/profile
效果
配置完成 path 变量后,我们就可以在系统的任意目录下运行 hadoop 和 hbase 的 bin 下面的脚本和程序了:
这里我们使用 hadoop version 来测试下
配置 hbase-env.sh
我们需要将必要的环境变量重新写入一份到 hbase-env.sh,并且需要额外做两项 zookeeper 和 hbase classpath 的配置。
下面使用 vim 编辑器打开文件:
hadoop@huxiaofan-ubuntu:~$ vim /usr/local/hbase/conf/hbase-env.sh
追加如下内容:
# JAVA_HOME
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
# HBASE_CLASSPATH
export HBASE_CLASSPATH=/usr/local/hadoop/conf
# HBASE_MANAGES_ZK
export HBASE_MANAGES_ZK=true
其中 HBASE_CLASSPATH 用来指定 hbase 的配置文件目录。 HBASE_MANAGES_ZK=true 表示使用 hbase 自带的 zookeeper,不使用自己搭建的独立 zookeeper。
配置 hbase-site.xml
hbase-site.xml 位于 /usr/local/hadoop/conf 也就是 Hbase 默认的配置文件保存目录下。这里我们直接配置伪分布式模式。
初始内容:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hbase.cluster.distributed</name>
<value>false</value>
</property>
<property>
<name>hbase.tmp.dir</name>
<value>./tmp</value>
</property>
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
</configuration>
这里使用 vim 命令直接编辑:
完整配置:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://localhost:9000/hbase</value>
<!-- 用于指定 Hbase 的数据存储位置 -->
<!-- 由于在伪分布式模式下,我们使用 Hadoop 的 HDFS 来存储 Hbase 的数据 -->
<!-- 所以这一步的 hbase.rootdir 设置为 Hbase 在 HDFS 的存储路径-->
<!-- 如果是单机 模式,就直接使用 file://路径 来指定文件位置-->
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
<!-- 由于采用了伪分布式模式,需要使用到自带的 zookeeper -->
<!-- 所以这一项要设置为 true -->
</property>
<property>
<name>hbase.tmp.dir</name>
<value>./tmp</value>
</property>
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
</configuration>
运行和排错
到这里,按照教科书的说明,可以直接运行命令启动 Hadoop 和 Hbase 了。因为 Hbase 的文件存储依赖 Hadoop 的 HDFS,所以我们需要先启动 Hadoop 再启动 Hbase。
运行命令:
由于前面我们配置 path 变量的时候已经添加了 Hadoop 和 Hbase,所以现在可以直接运行启动脚本。
# 启动命令
start-all.sh
start-hbase.sh
使用 JPS 命令查看当前的 Java 进程运行状态:
出现下列的进程,可以看到进程已经全部启动。
应该出现的进程列表:
Jps
Hmaster
HQuorumPeer
NameNode
HregionServer
SecondaryNameNode
DataNode
排错 multiple SLF4J bindings
但是我们可以看到系统存在警告:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/local/hadoop/share/hadoop/common/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/local/hbase/lib/client-facing-thirdparty/slf4j-log4j12-1.7.30.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
……
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
127.0.0.1: running zookeeper, logging to /usr/local/hbase/bin/../logs/hbase-hadoop-zookeeper-huxiaofan-ubuntu.out
running master, logging to /usr/local/hbase/bin/../logs/hbase-hadoop-master-huxiaofan-ubuntu.out
出现这个错误的原因,是 Hadoop 中的 jar 包和 HBase 中的包版本不一致,就会出现对应的 warnning 信息
网上广为流传的方法是删除冲突 jar 包中的其中的一个来解决问题。但是在我的数次试验后,发现如果照这样操作,不论是删 Hadoop 里的 jar 包,还是删除 Hbase 里的包,都会出现启动时报错,找不到 java 类的 error。
本来只是一个 warring,删除后直接变成 Error。说明网上的这个方法肯定是行不通的。
最后几经努力,找到了正确的解决方案:只要在 hbase-env.sh 中加一行配置就行。
export HBASE_DISABLE_HADOOP_CLASSPATH_LOOKUP="true"
事实上这句话本来就在配置文件中存在,只要取消注释就行。这句话的作用就是禁止 Hbase 查找 Hadoop 的 Classs。
完成这波配置后,再次启动 Hbase:
可以看到刚才看到的长长一堆的报错都消失了。
排错 NoNode for /hbase/master
本来想着大功告成,可以进入 Hbase 的 shell 来操作数据库了。可现实又给了我当头一棒。我还是太年轻了,虽然 Hbase 启动成功了,但是一旦进入 Hbase Shell,输入 status 就又会再次报错。
hbase(main):001:0> status
ERROR: KeeperErrorCode = NoNode for /hbase/master
For usage try 'help "status"'
Took 0.0899 seconds
出现这个问题的原因是,我之前在保存 hbase-site.xml 配置文件的时候,对存储路径的部分进行了修改:
<name>hbase.rootdir</name>
<value>hdfs://localhost:9000/hbase</value>
我之前这一行填写的是 hdfs://127.0.0.1:9000/hbase
后面改成了 localhost 造成了这个问题
问题的根本原因是修改了 hdfs 的路径,导致了文件的不完整,hadoop 上文件与本地文件不一致。
解决方法参考了这篇文章 https://blog.csdn.net/haiyan09/article/details/99863987
- 关闭所有进程(hadoop 和 hbase)
- 启动 hadoop(因为需要操作 hdfs)
- 删除 /hbase 文件
这里我直接简单粗暴的把 jps 里面列出来的进程都 kill 掉了。然后直接启动 hadoop:
hadoop@huxiaofan-ubuntu:~$ start-all.sh
WARNING: Attempting to start all Apache Hadoop daemons as hadoop in 10 seconds.
WARNING: This is not a recommended production deployment configuration.
WARNING: Use CTRL-C to abort.
Starting namenodes on [localhost]
Starting datanodes
Starting secondary namenodes [huxiaofan-ubuntu]
Starting resourcemanager
Starting nodemanagers
查看hadoop 根目录:
hadoop@huxiaofan-ubuntu:~$ hadoop fs -ls /
Found 1 items
drwxr-xr-x - hadoop supergroup 0 2020-10-12 21:18 /hbase
退出安全模式:
hadoop@huxiaofan-ubuntu:~$ hdfs dfsadmin -safemode leave
Safe mode is OFF
删除 /hbase 文件:
hadoop@huxiaofan-ubuntu:~$ hadoop fs -rm -r /hbase
Deleted /hbase
hadoop@huxiaofan-ubuntu:~$ hadoop fs -ls /
启动 Hbase:
hadoop@huxiaofan-ubuntu:~$ start-hbase.sh
现在我们进入 Hbase Shell 然后运行 status 来看看现在还会不会报刚才的错误:
可以看到现在已经可以正常显示状态了。
排错 Unable to load native-hadoop library
我们可以看到,刚才在启动 Hbase Shell 的时候,系统还有一条警告:
hadoop@huxiaofan-ubuntu:~$ hbase shell
2020-10-12 21:18:43,234 WARN [main] util.NativeCodeLoader: Unable to load native-hadoop library for your platforble
当然这条警告是不影响 Hbase 运行的。也可以完全忽视掉它。当然眼不见心不烦,我选择手动修复这一条警告,而且这个库文件有助于提高 Hbase 的运行速度:
这个问题,官方已经给出了解决方案:
使用命令测试:hadoop checknative -a
后发现,我的 hadoop 其实是已经包含了Hadoop Native Libraries 的。跳出警告的原因就是 Hbase 没有识别到这个库。
要做的很简单:
我们只需要把库文件的地址加入到 hbase-env.sh 就可以了。
# 在 hbase-env.sh 中追加下面内容
# LIB
export LD_LIBRARY_PATH=/usr/local/hadoop/lib/native:$LD_LIBRARY_PATH
使用 vim 进行编辑:
注,如果你的 Hadoop 没法加载本地库,则需要把下面的内容追加到 /etc/profile 或者 /usr/local/hadoop/etc/hadoop/hadoop-env.sh 中:
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_HOME=/usr/local/hadoop
export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib:$HADOOP_COMMON_LIB_NATIVE_DIR"
保存后,重新启动 Hbase,进入 Hbase Shell 的时候,就不会跳出上面那样的警告啦。
Tips:启动和关闭脚本
配置完成环境变量后我们可以使用 shart-dfs.sh 来启动 hadoop。使用 stop-dfs.sh 或者 stop-all.sh 来关闭 hadoop。
但是对于 hbase 来说,启动和关闭 hbase 需要单独的命令:
# 启动 hbase
start-hbase.sh
# 停止 hbase
stop-hbase.sh
使用 hadoop 的 stop-all.sh,虽然从名字上来看可以用来停止所有 hadoop 相关的服务。但事实上没法停止 hbase。如下图:
stop-all.sh 卡住
对于这种情况,我们可以运行 hbase-daemon.sh stop master
先停止 master 节点服务。再运行 stop-all.sh
开启 Hbase 的网页控制面板
关于开启 hadoop WEB 信息界面的,可以查看我的上一篇文章
与 hadoop 不同, hbase的master web 默认是不运行的,所以需要自己配置默认端口。 所需要做的只要在 hbase-site.xml 中加入以下内容即可:
<property>
<name>hbase.master.info.port</name>
<value>16010</value>
<!-- WEB 管理界面端口 -->
</property>
<property>
<name>hbase.regionserver.info.port</name>
<value>16030</value>
<!-- 节点信息查看端口 -->
</property>
以上配置文件的端口号都可以自定义。
下面只需要在防火墙放行端口就可以通过宿主机的浏览器进行访问啦!
iptables -I INPUT -p tcp --dport 16010 -j ACCEPT
iptables -I INPUT -p tcp --dport 16030 -j ACCEPT
service iptables restart
重启相关服务后,应该可以看到和我一样的界面:
完整配置文件
hbase-env.sh
export HBASE_DISABLE_HADOOP_CLASSPATH_LOOKUP="true"
# Override text processing tools for use by these launch scripts.
# export GREP="${GREP-grep}"
# export SED="${SED-sed}"
# JAVA_HOME
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
# HBASE_CLASSPATH
export HBASE_CLASSPATH=/usr/local/hadoop/conf
# HBASE_MANAGES_ZK
export HBASE_MANAGES_ZK=true
# LIB
export LD_LIBRARY_PATH=/usr/local/hadoop/lib/native:$LD_LIBRARY_PATH
hbase-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://localhost:9000/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.master.info.port</name>
<value>16010</value>
</property>
<property>
<name>hbase.regionserver.info.port</name>
<value>16030</value>
</property>
<property>
<name>hbase.tmp.dir</name>
<value>/usr/local/hbase/tmp</value>
</property>
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
</configuration>

This blog is under a CC BY-NC-ND 4.0 Unported License
本文链接:https://coding.emptinessboy.com/2020/10/%E5%9F%BA%E4%BA%8E-Hadoop-%E4%BC%AA%E5%88%86%E5%B8%83%E5%BC%8F%E6%90%AD%E5%BB%BA-Hbase/