Springboot 系列 (24) - Springboot+HBase 大数据存储(二)| 安装配置 Apache HBase 和 Apache Zookeeper

发布时间 2023-03-23 12:39:15作者: 垄山小站


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

    本文在伪分布式 Hadoop 架构上安装配置 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

        $ cd ~/apps/hbase-2.4.4

        $ vim ./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://localhost:9000/hbase</value>
                </property>
            </configuration>


        $ vim ./conf/hbase-env.sh

            export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
            export HBASE_MANAGES_ZK=true    # 使用 HBase 内置的 Zookeeper

    3) 设置 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

    4) 链接 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

    5) 启动集群

        $ cd ~/apps

        # 启动 HDFS
        $ ./hadoop-3.2.2/sbin/start-dfs.sh

            Starting namenodes on [localhost]
            Starting datanodes
            Starting secondary namenodes [Test-Ubuntu20]

        # 启动 Yarn
        $ ./hadoop-3.2.2/sbin/start-yarn.sh

            Starting resourcemanager
            Starting nodemanagers

        # 启动 HBase
        $ ./hbase-2.4.4/bin/start-hbase.sh

        # 主机上查看节点
        $ jps

            9440 Jps
            7440 NameNode
            8962 HQuorumPeer
            8227 NodeManager
            8037 ResourceManager
            9080 HMaster
            7625 DataNode
            7838 SecondaryNameNode


        HMaster 就是 HBase 的进程,可以访问 http://localhost:16010(或 http://ip:16010)查看 HBase 页面。
        
        上文我们设置了使用 HBase 内置的 Zookeeper,Zookeeper 的默认端口是 2181,运行如下命令查看端口:

            $ netstat -ap | grep ':2181'

                tcp6     0    0 127.0.0.1:2181    [::]:*     LISTEN     78822/java

        很显然,HBase 内置的 Zookeeper 已经自动运行,内置 Zookeeper 的 Jar 文件在 lib 目录下。

    6) 停止集群

        $ 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,先按上述步骤在主机上安装配置 HBase,再把主机上的 hbase-2.4.4 目录复制到辅机的 home/xxx/apps 目录下,并在辅机上配置 HBASE_HOME、链接 Hadoop 的配置文件等。


3. 安装配置 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://localhost:9000/hbase</value>
                </property>
                <property>
                    <name>hbase.zookeeper.quorum</name>
                    <value>localhost</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

            export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
            export HBASE_MANAGES_ZK=false    # 使用外部独立的 Zookeeper

    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

        # 主机上查看节点
        $ jps

            90435 SecondaryNameNode
            90197 DataNode
            90053 NameNode
            89837 QuorumPeerMain
            93021 HMaster
            93359 Jps
            93199 HRegionServer
            90814 NodeManager
            90674 ResourceManager


        HMaster 就是 HBase 的进程,可以访问 http://localhost:16010(或 http://ip:16010)查看 HBase 页面。

    6) 停止集群

        $ 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

 

4. 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。