Springboot 系列 (24) - Springboot+HBase 大数据存储(二)| 安装配置 Apache HBase 和 Apache Zookeeper
Apache HBase 是 Java 语言编写的一款 Apache 开源的 NoSQL 型数据库,不支持 SQL,不支持事务,不支持 Join 操作,没有表关系。Apache HBase 构建在 Apache Hadoop 和 Apache Zookeeper 之上。
Apache HBase 的应用场景:
(1) 半结构化或非结构化数据:数据结构字段不确定、杂乱无章很难按一个概念去进行抽取、需要支持动态增加字段等类型的数据;
(2) 记录非常稀疏:RDBMS 的行有多少列是固定的,为 null 的列浪费了存储空间。HBase 为 null 的 Column 不会被存储,这样既节省了空间又提高了读性能;
(3) 多版本数据: 根据 Row key 和 Column key 定位到的 Value 可以有任意数量的版本值,因此对于需要存储变动历史记录的数据,用 HBase 非常方便;
(4) 超大数据量:RDBMS 面对超大数据量的对策是读写分离、分库、分表(垂直和水平两种切分),切分后很多查询和写操作需要借助第三方插件来完成,这样会降低数据库整体性能,并增加数据库操作和维护的难度。HBase 会自动水平切分扩展,HBase 构建在分布式文件系统 (HDFS) 之上,HDFS 保障其数据可靠性,MapReduce 保障海量数据分析的高性能。
Apache HBase: https://hbase.apache.org/
Apache Zookeeper 是由 Apache Hadoop 的 Zookeeper 子项目发展而来,现在已经成为了 Apache 的顶级项目。Zookeeper 为分布式系统提供了高效可靠且易于使用的协同服务,它可以为分布式应用提供相当多的服务,诸如统一命名服务,配置管理,状态同步和组服务等。
Apache Zookeeper 接口简单,开发人员不必过多地纠结在分布式系统编程难于处理的同步和一致性问题上,可以使用 Zookeeper 提供的现成 (off-the-shelf) 服务来实现分布式系统的配置管理,组管理,Leader 选举等功能。
Apache Zookeeper: http://zookeeper.apache.org/
在 “Springboot 系列 (23) - Springboot+HBase 大数据存储(一)| 安装配置 Apache Hadoop” 里我们安装配置了 Apache Hadoop,本文介绍 Apache HBase 和 Apache Zookeeper 的安装配置过程。
1. 系统环境
操作系统:Ubuntu 20.04
Java 版本:openjdk 11.0.18
Hadoop 版本:3.2.2
Zookeeper 版本:3.6.3
HBase 版本:2.4.4
注:HBase 2.4.4 和 Hadoop 3.2.2 是兼容的,Hadoop 的版本不是越高越好,必须注意两者的兼容性问题。具体兼容性问题,可以查看 https://hbase.apache.org/book.html#_configuration_files
2. 安装配置 HBase
1) 下载 HBase访问 https://archive.apache.org/dist/hbase/2.4.4/hbase-2.4.4-bin.tar.gz,下载 hbase-2.4.4-bin.tar.gz 保存到 ~/apps 目录,apps 目录是当前 Linux 用户 (假设为 xxx) 下的目录,即 /home/xxx/apps。
$ cd ~/apps
$ tar -zvxf hbase-2.4.4-bin.tar.gz
$ mv hbase-2.4.4-bin hbase-2.4.4
2) 设置 HBASE_HOME
$ sudo vim /etc/profile
... JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 JRE_HOME=$JAVA_HOME/jre HADOOP_HOME=/home/xxx/apps/hadoop-3.2.2 HBASE_HOME=/home/xxx/apps/hbase-2.4.4 CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$HADOOP_HOME/bin:$HBASE_HOME/bin export JAVA_HOME JRE_HOME HADOOP_HOME HBASE_HOME CLASS_PATH PATH
$ source /etc/profile
$ echo $HBASE_HOME
home/xxx/apps/hbase-2.4.4
3. 单机模式 HBase
单机模式下,HBase 和内置的 Zookeeper 使用本地文件系统,不需要配置和启动 Hadoop (HDFS)。
1) 修改 HBase 配置文件
$ cd ~/apps
$ vim ./hbase-2.4.4/conf/hbase-site.xml
<configuration> <property> <name>hbase.cluster.distributed</name> <value>false</value> </property> <property> <name>hbase.tmp.dir</name> <value>/home/xxx/apps/hbase-2.4.4/tmp</value> </property> <property> <name>hbase.unsafe.stream.capability.enforce</name> <value>false</value> </property> <property> <name>hbase.rootdir</name> <value>file:///home/xxx/apps/hbase-2.4.4/tmp/hbase</value> </property> <property> <name>hbase.zookeeper.property.dataDir</name> <value>/home/xxx/apps/hbase-2.4.4/tmp/zookeeper</value> </property> </configuration>
注:file:// 或 file: 表示存储于本地文件系统上,hbase 数据存储在 /home/xxx/apps/hbase-2.4.4/tmp/hbase 目录下,内置的 zookeeper 数据存储在 /home/xxx/apps/hbase-2.4.4/tmp/zookeeper 目录下。
$ vim ./hbase-2.4.4/conf/hbase-env.sh
... # 使用 HBase 内置的 Zookeeper export HBASE_MANAGES_ZK=true export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
2) 启动 HBase
$ cd ~/apps
$ ./hbase-2.4.4/bin/start-hbase.sh
running master, logging to /home/xxx/apps/hbase-2.4.4/logs/hbase-xxx-master-hadoop-master-vm.out WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.apache.hadoop.hbase.util.UnsafeAvailChecker (file:/home/xxx/apps/hbase-2.4.4/lib/hbase-common-2.4.4.jar) to method java.nio.Bits.unaligned() WARNING: Please consider reporting this to the maintainers of org.apache.hadoop.hbase.util.UnsafeAvailChecker WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release
# 查看节点
$ jps
5765 HMaster
6092 Jps
注:HMaster 就是 HBase 的进程,可以访问 http:/localhost:16010(或 http://ip:16010)查看 HBase 页面。
在 hbase-env.sh 里设置使用 HBase 内置的 Zookeeper,Zookeeper 的默认端口是 2181,运行如下命令查看端口:
$ netstat -ap | grep ':2181'
tcp6 0 0 127.0.0.1:2181 [::]:* LISTEN 78822/java
很显然,HBase 内置的 Zookeeper 已经自动运行,内置 Zookeeper 的 Jar 文件在 lib 目录下。
3) 使用 HBase Shell 连接 HBase
$ cd ~/apps
$ ./hbase-2.4.4/bin/hbase shell
WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.apache.hadoop.hbase.util.UnsafeAvailChecker (file:/home/tkuang/apps/hbase-2.4.4/lib/hbase-common-2.4.4.jar) to method java.nio.Bits.unaligned() WARNING: Please consider reporting this to the maintainers of org.apache.hadoop.hbase.util.UnsafeAvailChecker WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release 2023-04-11 14:09:07,013 WARN [main] util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable HBase Shell Use "help" to get list of supported commands. Use "exit" to quit this interactive shell. For Reference, please visit: http://hbase.apache.org/2.0/book.html#shell Version 2.4.4, r20e7ba45b0c3affdc0c06b1a0e5cbddd1b2d8d18, Mon Jun 7 15:31:55 PDT 2021 Took 0.0019 seconds # 显示表 hbase:001:0> list TABLE 0 row(s) Took 0.2638 seconds => [] # 显示版本 hbase:002:0> version 2.4.4, r20e7ba45b0c3affdc0c06b1a0e5cbddd1b2d8d18, Mon Jun 7 15:31:55 PDT 2021 Took 0.0003 seconds # 显示 HBase 服务状态 hbase:003:0> status 1 active master, 0 backup masters, 1 servers, 0 dead, 2.0000 average load Took 0.0506 seconds # 退出 hbase:004:0> exit
# 关闭 HBase
$ ./hbase-2.4.4/bin/stop-hbase.sh
stopping hbase ............
4. 伪分布式 HBase 集群
本文在伪分布式 Hadoop 架构上部署 HBase,伪分布式 Hadoop 的主机名为 hadoop-master-vm,使用内置的 Zookeeper。
1) 修改 HBase 配置文件
$ cd ~/apps
$ vim ./hbase-2.4.4/conf/hbase-site.xml
<configuration> <property> <name>hbase.cluster.distributed</name> <value>false</value> </property> <property> <name>hbase.tmp.dir</name> <value>/home/xxx/apps/hbase-2.4.4/tmp</value> </property> <property> <name>hbase.unsafe.stream.capability.enforce</name> <value>false</value> </property> <property> <name>hbase.rootdir</name> <value>hdfs://hadoop-master-vm:9000/hbase</value> </property> <property> <name>hbase.zookeeper.property.dataDir</name> <value>/home/xxx/apps/hbase-2.4.4/tmp/zookeeper</value> </property> </configuration>
2) 链接 Hadoop 的配置文件
$ cd ~/apps/hbase-2.4.4/conf
$ ln -s ~/apps/hadoop-3.2.2/etc/hadoop/core-site.xml core-site.xml
$ ln -s ~/apps/hadoop-3.2.2/etc/hadoop/hdfs-site.xml hdfs-site.xml
3) 启动集群
$ cd ~/apps
# 启动 HDFS
$ ./hadoop-3.2.2/sbin/start-dfs.sh
Starting namenodes on [hadoop-master-vm]
Starting datanodes
Starting secondary namenodes [hadoop-master-vm]
# 启动 Yarn
$ ./hadoop-3.2.2/sbin/start-yarn.sh
Starting resourcemanager
Starting nodemanagers
# 启动 HBase
$ ./hbase-2.4.4/bin/start-hbase.sh
/home/xxx/apps/hadoop-3.2.2/libexec/hadoop-functions.sh: line 2366: HADOOP_ORG.APACHE.HADOOP.HBASE.UTIL.GETJAVAPROPERTY_USER: invalid variable name /home/xxx/apps/hadoop-3.2.2/libexec/hadoop-functions.sh: line 2461: HADOOP_ORG.APACHE.HADOOP.HBASE.UTIL.GETJAVAPROPERTY_OPTS: invalid variable name SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/home/xxx/apps/hadoop-3.2.2/share/hadoop/common/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/xxx/apps/hbase-2.4.4/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] running master, logging to /home/xxx/apps/hbase-2.4.4/logs/hbase-xxx-master-hadoop-master-vm.out /home/xxx/apps/hadoop-3.2.2/libexec/hadoop-functions.sh: line 2366: HADOOP_ORG.APACHE.HADOOP.HBASE.UTIL.GETJAVAPROPERTY_USER: invalid variable name /home/xxx/apps/hadoop-3.2.2/libexec/hadoop-functions.sh: line 2461: HADOOP_ORG.APACHE.HADOOP.HBASE.UTIL.GETJAVAPROPERTY_OPTS: invalid variable name SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/home/xxx/apps/hadoop-3.2.2/share/hadoop/common/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/xxx/apps/hbase-2.4.4/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] WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.apache.hadoop.hbase.util.UnsafeAvailChecker (file:/home/xxx/apps/hbase-2.4.4/lib/hbase-common-2.4.4.jar) to method java.nio.Bits.unaligned() WARNING: Please consider reporting this to the maintainers of org.apache.hadoop.hbase.util.UnsafeAvailChecker
注:显示了多条 hadoop 的警告信息,可以修改 hbase-env.sh 文件来忽略 hadoop 的警告信息。
$ vim ./hbase-2.4.4/conf/hbase-env.sh
...
export HBASE_DISABLE_HADOOP_CLASSPATH_LOOKUP=true
重启 HBase。
# 主机上查看节点
$ jps
8258 ResourceManager 9203 Jps 7651 NameNode 7829 DataNode 8042 SecondaryNameNode 8590 NodeManager 8863 HMaster
注:HMaster 就是 HBase 的进程,可以访问 http://hadoop-master-vm:16010(或 http://ip:16010)查看 HBase 页面。
HBase 内置 Zookeeper 的默认端口是 2181,运行如下命令查看端口:
$ netstat -ap | grep ':2181'
tcp6 0 0 127.0.0.1:2181 [::]:* LISTEN 8863/java
内置的 Zookeeper 已经自动运行。
4) 使用 HBase Shell 连接 HBase
$ cd ~/apps
$ ./hbase-2.4.4/bin/hbase shell
... HBase Shell Use "help" to get list of supported commands. Use "exit" to quit this interactive shell. For Reference, please visit: http://hbase.apache.org/2.0/book.html#shell Version 2.4.4, r20e7ba45b0c3affdc0c06b1a0e5cbddd1b2d8d18, Mon Jun 7 15:31:55 PDT 2021 Took 0.0011 seconds hbase:001:0> status 1 active master, 0 backup masters, 1 servers, 0 dead, 2.0000 average load Took 0.3670 seconds
5) 停止集群
$ cd ~/apps
# 停止 HBase
$ ./hbase-2.4.4/bin/stop-hbase.sh
# 停止 Yarn
$ ./hadoop-3.2.2/sbin/stop-yarn.sh
# 停止 HDFS
$ ./hadoop-3.2.2/sbin/stop-dfs.sh
注:在伪分布式 Hadoop 架构上部署 HBase,先查看 hdfs 文件系统是否正常,确保 namenode 使用命令 hdfs namenode -format 格式过。
集群/分布式 Hadoop 架构上安装配置 HBase,先按上述步骤在主机上安装配置 HBase,再把主机上的 hbase-2.4.4 目录复制到辅机的 home/xxx/apps 目录下,并在辅机上配置 HBASE_HOME、链接 Hadoop 的配置文件等。
5. 安装配置 Zookeeper
HBase 有内置的 Zookeeper,在实际应用中,可能会因为版本、或要使用已有的分布式 Zookeeper 等原因,需要部署外部独立运行的 Zookeeper。
配置 HBase 使用外部独立的 Zookeeper,先要使内置的 Zookeeper 不受 HBase 管理,再修改 HBase 运行模式为分布式。
1) 下载 Zookeeper
访问 https://downloads.apache.org/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz,下载 apache-zookeeper-3.6.3-bin.tar.gz 保存到 ~/apps 目录。
$ cd ~/apps
$ tar -zvxf apache-zookeeper-3.6.3-bin.tar.gz
$ mv apache-zookeeper-3.6.3-bin zookeeper-3.6.3
2) 设置 data 目录
$ cd zookeeper-3.6.3
$ mkdir data
$ cp conf/zoo_sample.cfg conf/zoo.cfg
$ vim conf/zoo.cfg
dataDir = /home/xxx/apps/zookeeper-3.6.3/data
clientPort = 2182
maxClientCnxns = 100
注:把独立安装的 Zookeeper 的端口设置为 2182,区别于内置的 Zookeeper 的端口 2181。
ZooKeeper 默认同一个 IP地址连接到服务器的最大连接数(maxClientCnxns)是 10,可以设置参数 maxClientCnxns = 0 (即无限制),为了防止 DOS 网络攻击,请根据实际情况设置。
3) 运行 Zookeeper
# 启动 server
$ ./bin/zkServer.sh start
Using config: /home/xxx/apps/zookeeper-3.6.3/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
# 运行 cli
$ ./bin/zkCli.sh -server localhost:2182
Connecting to localhost:2182 2023-03-20 18:43:51,925 [myid:] - INFO [main:Environment@98] - Client environment:zookeeper.version=3.6.3--6401e4ad2087061bc6b9f80dec2d69f2e3c8660a, built on 04/08/2021 16:35 GMT ... WATCHER:: WatchedEvent state:SyncConnected type:None path:null [zk: localhost:2182(CONNECTED) 0] ls / [hbase, zookeeper] [zk: localhost:2182(CONNECTED) 2] quit
# 停止 server
$ ./bin/zkServer.sh stop
Stopping zookeeper ... STOPPED
4) 配置 HBase + Zookeeper (独立的)
$ cd ~/apps/hbase-2.4.4
$ vim ./conf/hbase-site.xml
<configuration> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.tmp.dir</name> <value>/home/xxx/apps/hbase-2.4.4/tmp</value> </property> <property> <name>hbase.unsafe.stream.capability.enforce</name> <value>false</value> </property> <property> <name>hbase.rootdir</name> <value>hdfs://hadoop-master-vm:9000/hbase</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>hadoop-master-vm</value> </property> <property> <name>hbase.zookeeper.property.clientPort</name> <value>2182</value> </property> </configuration>
注:把 hbase.cluster.distributed 设置为 true,否则 HBase 仍然会以 standalone 模式运行,依然会去启动内置的 Zookeeper。
$ vim ./conf/hbase-env.sh
... # 使用外部独立的 Zookeeper export HBASE_MANAGES_ZK=false export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
注:同一主机上,如果之前部署过内置 Zookeeper,可能需要清除 HBase 和 Hadoop 的临时目录 (默认在 /tmp 下,一般在配置文件里设置)。查看 Hadoop (hdfs) 文件系统是否正常,如果有需要可以删除 data 目录, 并运行 hdfs namenode -format 命令重新格式化。
5) 启动集群
$ cd ~/apps
# 启动 Zookeeper
$ ./zookeeper-3.6.3/bin/zkServer.sh start
# 启动 HDFS
$ ./hadoop-3.2.2/sbin/start-dfs.sh
# 启动 Yarn
$ ./hadoop-3.2.2/sbin/start-yarn.sh
# 启动 HBase
$ ./hbase-2.4.4/bin/start-hbase.sh
注:运行 start-hbase.sh,启动 HMaster 并会自动启动 HRegionServe。如果不想启动 HRegionServer,可以运行如下命令:
$ ./hbase-2.4.4/bin/hbase-daemon.sh start master
相应的停止命令:
$ ./hbase-2.4.4/bin/hbase-daemon.sh stop master
# 主机上查看节点
$ jps
90435 SecondaryNameNode 90197 DataNode 90053 NameNode 89837 QuorumPeerMain 93021 HMaster 93359 Jps 93199 HRegionServer 90814 NodeManager 90674 ResourceManager
HMaster 就是 HBase 的进程,可以访问 http://hadoop-master-vm:16010(或 http://ip:16010)查看 HBase 页面。
6) 使用 HBase Shell 连接 HBase
$ cd ~/apps
$ ./hbase-2.4.4/bin/hbase shell
... HBase Shell Use "help" to get list of supported commands. Use "exit" to quit this interactive shell. For Reference, please visit: http://hbase.apache.org/2.0/book.html#shell Version 2.4.4, r20e7ba45b0c3affdc0c06b1a0e5cbddd1b2d8d18, Mon Jun 7 15:31:55 PDT 2021 Took 0.0021 seconds hbase:001:0> status 1 active master, 0 backup masters, 1 servers, 0 dead, 2.0000 average load Took 0.4602 seconds
7) 停止集群
$ cd ~/apps
# 停止 HBase
$ ./hbase-2.4.4/bin/stop-hbase.sh
# 停止 Yarn
$ ./hadoop-3.2.2/sbin/stop-yarn.sh
# 停止 HDFS
$ ./hadoop-3.2.2/sbin/stop-dfs.sh
# 停止 Zookeeper
$ ./zookeeper-3.6.3/bin/zkServer.sh stop
6. HBase 的表模型
HBase 基于 Google 的 BigTable 演化而来,是一个分布式海量列式非关系型数据库系统。
介绍 HBase 列存储之前,先看一下 RDBMS 是如何存储数据的,比如 MySQL 的表:
ID | NAME | AGE | SALARY | JOB |
1 | Tom | 12 | Student | |
2 | Jerry | 3000 | Engineer |
注:MySQL 的空值字段,也占用存储空间。
如果采用列存储方式,结构示意如下:
rowkey:1 name:Tom
rowkey:1 age:12
rowkey:1 job:Student
rowkey:2 name:Jerry
rowkey:2 salary:3000
rowkey:2 job:Engineer
...
HBase 存储结构如下:
RowKey | Column Family | Column Qualifer | TimeStamp | Type | Value |
1 | base_info | name | t1 | Put | Tom |
1 | base_info | age | t2 | Put | 12 |
1 | base_info | job | t3 | Put | Student |
2 | base_info | name | t4 | Put | Jerry |
2 | base_info | salary | t5 | Put | 3000 |
2 | base_info | job | t6 | Put | Engineer |
HBase 的表模型相关的一些概念:
概念 | 描述 |
Namespace (数据库) | 命名空间,每个命名空间下有多个表。HBase 自带两个命名空间:hbase 存放 HBase 内置表,default 是用户默认使用的命名空间。 |
Table (表) | HBase 定义表时只需要声明列族即可,数据属性都在列族的定义中定义,不需要声明具体的列。 |
RoW(一行逻辑数据) | HBase 表中的每行数据都由一个 Rowkey 和多个 Column(列)组成。一个行包含了多个列,这些列通过列族来分类,行中的数据所属列族只能从该表所定义的列族中选取,不能定义这个表中不存在的列族,否则报错 NoSuchColumnFamilyException。 |
Rowkey (每行数据主键) | Rowkey 由用户指定的一串不重复的字符串定义,是一行的唯一标识!数据是按照 RowKey 的字典顺序存储的,并日查询数据时只能根据 RowKey 进行检素,所以 RowKey 的设计十分重要。 |
Column Family(列族) | 列族是多个列的集合。一个列族可以动态地灵活定义多个列。表的相关属性大部分都定义在列族上,同一个表里的不同列族可以有完全不同的属性配置,但是同一个列族内的所有列都会有相同的属性。列族存在的意义是HBase会把相同列族的列尽量放在同一台机器上,所以说,如果想让某几个列被放到一起,你就给他们定义相同的列族。 |
Column Qualifier(列) | Hbase 中的列是可以随意定义的,一个行中的列不限名字、不限数量,只限定列族。因此列必须低赖于列族存在!列的名称前必须带着其所属的列族。例如 basic_info:name |
TimeStamp (时间戳|版本) | 用于标识数据的不同版本 (version)。时间戳默认由系统指定,也可以由用户显式指定。在读取单元格的数据时,版本号可以省略,如果不指定,Hbase 默认会获取最后一版本的数据返回。 |
Cell | 一个列中可以存储多个版本的数据,每个版本就称为一个单元格 (Cell) 。在 HBase 底层以 KV 形式存储,key 为(rowkey,column,timestamp,type),值为 value,其中 type 的类型 Put/Delete 。 |
Region(表的分区) | Region 由一个表的若干行组成。在 Region 中行的排序按照行键 (rowkey) 字典排序。Region 不能跨 RegionSever,且当数据量大的时候,HBase 会拆分 Region。 |