HBase基本概念
从 1970 年开始,大多数的公司数据存储和维护使用的是关系型数据库,大数据技术出现后,很多拥有海量数据的公司开始选择像Hadoop的方式来存储海量数据。
Hadoop使用分布式文件系统HDFS来存储海量数据,并使用 MapReduce 来处理。Hadoop擅长于存储各种格式的庞大的数据,任意的格式甚至非结构化的处理
Hadoop主要是实现批量数据的处理,并且通过顺序方式访问数据,要查找数据必须搜索整个数据集, 如果要进行随机读取数据,效率较低。
年份 | 重大事件 |
---|---|
2006年11月 | Google发布BigTable论文. |
2007年10月 | 发布第一个可用的HBase版本,基于Hadoop 0.15.0 |
2008年1月 | HBase成为Hadoop的一个子项目 |
2010年5月 | HBase成为Apache的顶级项目 |
结构:
功能:
结构:
功能:
HDFS:
HBase:
Hive:
HBase:
HBase的安装是建立在Hadoop之上的,所以请先简单学习一下Hadoop的使用和安装教程:
HBase集群内的不同组件之间需要进行通信,因此需要放行一些端口,具体如下:
如果你启用了HBase的Kerberos安全认证,还需要放行以下端口:
请注意,上述端口是HBase的默认端口,如果你在配置HBase时更改了某些端口,则需要放行相应的端口。
在ZooKeeper集群中,以下是需要放行的端口:
这三个端口是ZooKeeper集群通信的必要端口,确保这些端口在防火墙中正确地打开,以确保ZooKeeper集群能够正常通信。
最暴力的方法就是放行全部端口,省得麻烦。
# -C 指定解压后的文件存放目录
tar -xvzf hbase-2.1.0.tar.gz -C ../server/
cd /export/server/hbase-2.1.0/conf
vim hbase-env.sh
# 第28行
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HBASE_MANAGES_ZK=false
<configuration>
<!-- HBase数据在HDFS中的存放的路径 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://node1:8020/hbase</value>
</property>
<!-- Hbase的运行模式。false是单机模式,true是分布式模式。若为false,Hbase和Zookeeper会运行在同一个JVM里面 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- ZooKeeper的地址 -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>node1,node2,node3</value>
</property>
<!-- ZooKeeper快照的存储位置 -->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/export/server/apache-zookeeper-3.6.0-bin/data</value>
</property>
<!-- V2.1版本,在分布式情况下, 设置为false -->
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
</configuration>
export HBASE_MANAGES_ZK=false
是一个HBase环境变量的设置,用于告诉HBase不要启动自己的ZooKeeper服务。如果你的HBase集群中已经有一个独立的ZooKeeper集群在运行,你就可以将该变量设置为false
,从而避免HBase再次启动ZooKeeper服务,节省资源和避免冲突。
具体来说,当HBASE_MANAGES_ZK
环境变量的值为true
时,HBase会在启动时自动启动一个ZooKeeper服务,用于协调和管理HBase的分布式服务;当该值为false
时,HBase则不会启动自己的ZooKeeper服务,而是依赖于已有的ZooKeeper服务。
需要注意的是,在设置该环境变量时,需要确保你的HBase集群中已经有一个可用的ZooKeeper集群,并且HBase的配置文件中也已经正确指定了该ZooKeeper集群的地址。否则,将该变量设置为false
可能会导致HBase服务无法正常工作。
当将HBASE_MANAGES_ZK
属性设置为false
后,HBase将不会启动自己的ZooKeeper服务,而是依赖于一个外部的ZooKeeper集群。在这种情况下,你需要在HBase的配置文件中指定外部ZooKeeper集群的地址。
具体来说,你需要在HBase的配置文件中设置以下属性:
<!-- 指定使用的ZooKeeper集群的地址 -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>zk1:2181,zk2:2181,zk3:2181</value>
</property>
在上面的配置中,hbase.zookeeper.quorum
属性用于指定外部ZooKeeper集群的地址。该属性的值为一个逗号分隔的ZooKeeper服务器列表,每个服务器都包含服务器的主机名和客户端连接端口号,格式为hostname:port
。在上面的示例中,zk1:2181,zk2:2181,zk3:2181
表示一个由3个ZooKeeper服务器组成的集群,分别运行在zk1
、zk2
和zk3
这三台主机上,客户端连接端口号均为2181。
需要注意的是,当将HBASE_MANAGES_ZK
属性设置为false
时,确保你的HBase集群中已经有一个可用的ZooKeeper集群,并且在HBase的配置文件中正确指定了该集群的地址。如果指定的ZooKeeper集群无法访问,或者配置文件中的地址有误,可能会导致HBase无法正常工作。
在HBASE_MANAGES_ZK=true的情况下,HBase会自动管理ZooKeeper的启动和关闭,并默认将hbase.zookeeper.quorum设置为localhost。因此,在这种情况下,不需要显式地配置hbase.zookeeper.quorum参数。但是,如果您想将ZooKeeper配置为运行在不同的节点上,那么仍然需要显式地配置hbase.zookeeper.quorum参数。
这里的坑在于,如果hbase.zookeeper.quorum未指定,则HBase将使用本地默认的Zookeeper,它只在启动HBase集群的节点上启动,并监听127.0.0.1地址。此时,只有在单节点或伪分布式模式下才能正常工作,无法在分布式集群中正常工作。因此,在分布式集群中,建议指定hbase.zookeeper.quorum参数,以确保HBase可以连接到正确的Zookeeper集合。
即便,我们将HBASE_MANAGES_ZK设置为true,启用HBase默认的zk集群,我们依然需要在分布式部署时,指定hbase.zookeeper.quorum参数,指明zk需要部署在哪几台节点上。
hbase.zookeeper.property.dataDir
配置是用来指定HBase使用ZooKeeper时,ZooKeeper数据快照的存储位置的。
具体来说,HBase在使用ZooKeeper时,需要将ZooKeeper的快照和事务日志存储在本地文件系统上,以保证ZooKeeper的数据持久性和可靠性。这些数据存储的位置可以通过HBase的配置文件来指定,其中hbase.zookeeper.property.dataDir
属性用于指定ZooKeeper快照的存储位置。
在上面的配置中,hbase.zookeeper.property.dataDir
属性被设置为/export/server/apache-zookeeper-3.6.0-bin/data
,表示ZooKeeper的快照将会被存储在/export/server/apache-zookeeper-3.6.0-bin/data
目录下。如果该目录不存在,HBase会尝试自动创建该目录。需要注意的是,这个目录必须有足够的空间来存储ZooKeeper的快照和事务日志。
# 配置Hbase环境变量
vim /etc/profile
export HBASE_HOME=/export/server/hbase-2.1.0
export PATH=$PATH:${HBASE_HOME}/bin:${HBASE_HOME}/sbin
#加载环境变量
source /etc/profile
cp $HBASE_HOME/lib/client-facing-thirdparty/htrace-core-3.1.0-incubating.jar $HBASE_HOME/lib/
vim regionservers
node1
node2
node3
cd /export/server
scp -r hbase-2.1.0/ node2:$PWD
scp -r hbase-2.1.0/ node3:$PWD
scp -r /etc/profile node2:/etc
scp -r /etc/profile node3:/etc
#在node2和node3加载环境变量
source /etc/profile
cd /export/onekey
# 启动ZK -- 如果使用habse内嵌的zk,则这里我们无需手动另开一个zk集群
./start-zk.sh
# 启动hadoop --- 参考上面给出的hadoop搭建教程
start-dfs.sh
# 启动hbase
start-hbase.sh
使用Jps命令,查看hadoop,zk,hbase相关进程是否都已经启动了:
# 启动hbase shell客户端
hbase shell
我的HBase集群部署在三台云服务器上,并且处于不同的局域网中,两台阿里云,一台华为云,由于HBase默认集群处于同一个内网中,所以对于我的部署环境而言,如果直接启动HBase集群,会出现很多问题。
下面我将列举我安装过程中出现的通信问题,以及如何解决这些问题,解决思路是什么。
通过查看zk日志,会发现集群间通信存在异常:
2023-05-10 00:25:30,128 ERROR [main] regionserver.HRegionServer: Failed construction RegionServer
org.apache.hadoop.hbase.ZooKeeperConnectionException: master:160000x0, quorum=node1:2181,node2:2181,node3:2181, baseZNode=/hbase Unexpected KeeperException creating base node
这三个端口是ZooKeeper集群通信的必要端口,确保这些端口在防火墙中正确地打开,以确保ZooKeeper集群能够正常通信。
防火墙明明放开了呀!为啥还是不行呀!
netstat -nltp | grep 3888
netstat -nltp | grep 2888
netstat -nltp | grep 2181
hbase自动启动的zk,3888端口默认监听的是127.0.0.1,如何通过设置让其监听0.0.0.0?
quorumListenOnAllIPs
是一个 ZooKeeper 配置参数,用于指定是否在所有 IP 地址上监听 quorum 端口。zookeeper.serverCnxnFactory.address
参数进行配置。hbase.zookeeper.property.quorumListenOnAllIPs=true
可以让自动启动的 ZooKeeper 监听 quorum 端口时在所有 IP 地址上监听。同时,也可以通过在 hbase-site.xml 中添加以下配置来指定 quorumListenOnAllIPs 参数的值:<property>
<name>hbase.zookeeper.property.quorumListenOnAllIPs</name>
<value>true</value>
</property>
Caused by: java.net.ConnectException: Call to node3/xxx:16000 failed on connection exception: org.apache.hbase.thirdparty.io.netty.channel.AbstractChannel$AnnotatedConnectException: connect(..) failed: Invalid argument: node3/xxx:16000
出现这个异常时,我首先排查是否因为node3节点只监听127.0.0.1地址上的16000端口所致:
[root@node3 logs]# netstat -nltpa | grep 16000
tcp6 0 0 127.0.0.1:16000 :::* LISTEN 244188/java
tcp6 0 0 127.0.0.1:16000 127.0.0.1:44959 ESTABLISHED 244188/java
从上面给出的结果可以看到,HBase进程正在监听本地127.0.0.1地址的16000端口,表示该端口只能在本地进行访问,而不对外开放。
默认情况下,HBase的HMaster进程会监听本地主机的16000端口,如果要让HBase监听所有地址上的16000端口,可以通过修改HMaster的配置文件实现。具体操作如下:
<property>
<name>hbase.master.ipc.address</name>
<value>0.0.0.0</value>
</property>
重启HBase集群,再次尝试,发现错误依然存在,这是为什么呢?
[root@node3 logs]# netstat -nltpa | grep 16000
tcp6 0 0 :::16000 :::* LISTEN 282806/java
tcp6 0 0 127.0.0.1:16000 127.0.0.1:56183 ESTABLISHED 282806/java
tcp6 0 0 127.0.0.1:56183 127.0.0.1:16000 ESTABLISHED 282909/java
通过再次查看16000端口的监听情况可知,此时HBase会监听16000端口上所有地址,所以这里应该没有问题了。
root@node2:/export/server/hbase-2.1.0/logs# telnet node3 16000
Trying 8.130.84.178...
Connected to node3.
Escape character is '^]'.
在node2节点上通过telnet 访问node3的16000端口,发现可以正常访问,说明也不是网络或者防火墙问题。
其实对于上面这个错误,我们应该把目光集中到日志中下面这部分来:
其实问题出在红色框框圈出来的两条WRAN日志中,首先我们需要知道:
因此,我们需要先确定16020端口是否只在本地地址进行监听:
root@node1:/export/server/hbase-2.1.0/logs# netstat -nltpa | grep 16020
tcp6 0 0 127.0.0.1:16020 :::* LISTEN 8419/java
<configuration>
<property>
<name>hbase.regionserver.ipc.address</name>
<value>0.0.0.0</value>
</property>
</configuration>
这样就可以让RegionServer监听所有可用的网络接口,而不仅仅是localhost。保存修改后,需要重启HBase RegionServer才能使配置生效。
但是,很不幸,启动后会发现错误依旧存在,难道问题不是出在这里吗?
只有node1节点上的HRegionServer可以与HMaster正常通信,Node2和Node3上的HRegionServer无法与HMaster正常通信。
再次回顾上面的日志,会发现抛出的是无效参数异常:
这里的无效参数到底指啥?
node1和node2节点处于不同的局域网下,node1节点上部署的HRegionServer可以与HMaster正常通信,并且/etc/hosts文件中配置127.0.0.1映射到node1,但是node2上部署的HRegionServer无法与HMaster正常通信。
这里直接给出答案:
这里不能改成公网地址,否则Hadoop和HBase运行都会报错,这里只能填写内网地址。
Hadoop部署的时候没有这个要求,127.0.0.1映射不会报错,HBase存在这个要求,不能采用127.0.0.1,而需要采用内网地址。
针对大概800TB存储空间的集群中每个Java进程的典型内存配置:
进程 | 堆 | 描述 |
---|---|---|
NameNode | 8 GB | 每100TB数据或每100W个文件大约占用NameNode堆1GB的内存 |
SecondaryNameNode | 8GB | 在内存中重做主NameNode的EditLog,因此配置需要与NameNode一样 |
DataNode | 1GB | 适度即可 |
ResourceManager | 4GB | 适度即可(注意此处是MapReduce的推荐配置) |
NodeManager | 2GB | 适当即可(注意此处是MapReduce的推荐配置) |
HBase HMaster | 4GB | 轻量级负载,适当即可 |
HBase RegionServer | 12GB | 大部分可用内存、同时为操作系统缓存、任务进程留下足够的空间 |
ZooKeeper | 1GB | 适度 |
推荐:
HBase单机版搭建就非常easy了,步骤如下:
cd /export/server/hbase-2.1.0/conf
vim hbase-env.sh
# 第28行
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HBASE_MANAGES_ZK=true
<configuration>
<!-- HBase数据在HDFS中的存放的路径 -->
<property>
<name>hbase.rootdir</name>
<value>file:/export/server/hbase/data</value>
</property>
<!-- Hbase的运行模式。false是单机模式,true是分布式模式。若为false,Hbase和Zookeeper会运行在同一个JVM里面 -->
<property>
<name>hbase.cluster.distributed</name>
<value>false</value>
</property>
<!-- ZooKeeper快照的存储位置 -->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/export/server/apache-zookeeper-3.6.0-bin/data</value>
</property>
<!-- V2.1版本,在分布式情况下, 设置为false -->
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
</configuration>