HBase的部署和应用
一、HBase基础
1.1 HBase 定义
Apache HBase 是一种基于 HDFS 的 NoSQL 数据库,具备分布式、可扩展、面向列的特性,专为存储和处理海量数据而设计。
什么是 NoSQL?
NoSQL 是 "
Not Only SQL" 的缩写,表示这类数据库不仅仅依赖传统的关系型数据库模型。NoSQL 数据库通常不使用表格、行、列的方式来组织数据,而是采用更灵活的方式,例如键值对、文档或图结构。
HBase 的作用
HBase 是一种分布式数据库系统,专为处理大规模结构化和半结构化数据设计。其主要作用包括:
高效存储和快速读写:能够管理大规模数据,支持快速的随机读写操作,适合存储数十亿行、数百万列的数据。
实时处理:支持低延迟的数据查询和更新,适合需要频繁写入和实时读取的场景,如日志分析和监控系统。
弹性扩展:可以根据数据量的增长轻松扩展到数百或数千台服务器。
大数据生态集成:与 Hadoop 紧密集成,利用 HDFS 存储,MapReduce 处理,Zookeeper 提供协调,适合大数据环境。
1.2 HBase 数据模型
1.2.1 HBase 逻辑结构
HBase 表由行和列组成,每一行由一个行键(Row Key)唯一标识,列被划分为若干个列族(Column Family)。
行键在 HBase 中的作用类似于关系型数据库中的主键,用于唯一标识每一行数据。
一个列族可以包含任意多个列,列族定义了列的逻辑分组。
HBase 将同一列族中的数据存储在相同的文件夹下,由多个 HFile 文件进行存储。
同一列族中的数据存储在多个 HFile 文件中,并不是所有的列都存储在同一个文件中。
当一个 HFile 文件达到一定大小后,HBase 会将该文件分裂(split),形成多个Region。每个 Region 负责一部分行键的范围,并且 Region 中的数据也会按列族存储在不同的 HFile 中。
对于同一个行键,如果它在不同的列族中都有数据,这些列族的数据将分别存储在对应列族的 HFile 文件中,HFile 文件中也会记录该行键。
换句话说,一行数据可能涉及多个列族,每个列族可以包含多个列。对于某一行数据来说,列族文件中只存储该行键在该列族中有值的列(不会存储空值或 null 值,不占用存储空间)。这使得 HBase 在存储稀疏数据时非常高效。

解读:
列(Column):
在 HBase 中,列是每个字段的数据,比如名字、城市、电话等。不同于传统数据库,HBase 的列可以动态增加,你不需要提前定义所有的列。图中的
name、city、phone就是列。列族(Column Family):
列族是把相关的列放在一起组成的一个组。你可以把它想象成一个大类,这个大类中的所有列会被存储在一起。在图中,
personal_info和office_info就是两个列族,分别包含了不同的列。比如personal_info包含name、city和phone。Row Key:
每一行数据都有一个唯一的行键(Row Key),类似于数据库中的主键。这个行键用来标识和查找整行数据。在图中,
row_key1、row_key2就是行键,代表了不同人的数据。行键按照字母顺序排列,因此查找数据时会更快。Region:
Region 是 HBase 表的一部分,像是一个水平切片。一个表可能有很多行,HBase 会把这些行根据行键的范围分成不同的部分,每一部分就是一个 Region。图中用不同颜色的区域表示不同的 Region,比如
row_key1到row_key2可能在一个 Region 中,row_key3到row_key5在另一个 Region 中。Store:
Store 是 HBase 中的存储单元。每个列族的数据会存储在一个或多个 Store 中。你可以把 Store 想象成专门保存某个列族数据的文件夹。在图中,
personal_info和office_info都有它们自己的 Store,里面分别保存着对应列族的数据。每个 Region 会有多个 Store,因为一个 Region 可能包含多个列族的数据。图中的不同颜色区域显示了不同的 Region,这些 Region 里的列族数据会分别存储在对应的 Store 中。
HFile:
HFile 是实际存储数据的物理文件。每个 Store 会将其数据分成多个 HFile 文件来存储。
每个列族在一个 Region 中对应一个或多个 Store,每个 Store 由多个 HFile 组成。图中展示的是逻辑上的数据视图,而在物理存储上,这些不同列族的数据会存储在各自独立的文件中。
图中展示的每个
Store中的数据,最终会被写入一个或多个 HFile 文件。每个 HFile 文件存储的是列族中部分行的数据。
关系总结:
Region 是一个图书区,里面有多个 Store(书架),每个 Store 存放一个列族的数据。
Store 是一个书架,专门用于存放某个列族的数据,这些数据被分成多个 HFile(书本) 文件存储。
HFile 是书本,每本书存储了 Store 中一部分列族的数据。一个 Store 可能包含多个 HFile 文件,正如一个书架上可能有多本书。
举例
在图中,假设你要查找 row_key1 对应的名字、城市和电话数据,HBase 会根据 row_key1 直接找到属于 personal_info 列族的 name、city 和 phone 列的数据。这些数据会存储在 personal_info 的 Store 中。
如果你要查找 row_key1 对应的办公室电话和地址信息,HBase 会在 office_info 的 Store 中找到这些数据。
1.2.2 HBase 物理结构

说明: qualifier [ˈkwɒlɪfaɪər] 限定
上面的图是每条数据如何存储在HDFS上的。多加了TimeStamp(时间戳)和Type两个字段。
t3,t4两条数据就是对row_key1数据的phone进行修改的操作。
我们根据TimeStamp来判断,哪条数据是最新的数据。最新的数据会覆盖掉旧的那条数据
时间戳就是Unix时间戳(Unix timestamp),定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。然后时间戳是不会跟着时区的改变而改变,所以不管你在哪个时区,时间戳都是一致的。
Timestamp时间戳(相当于版本!!!)
注意:
1.必须把本机时间和服务器的时间调成一致!
2.因为存储数据的时候会保存timestamp,假如时间不一致的话,就会出现很多问题!
数据坐标

HBase中需要根据行键、列族、列限定符和时间戳来确定一个单元格,因此,可以视为一个“四维坐标”,
即[行键, 列族, 列限定符, 时间戳]

存储格式:多维稀疏排序Map
key的构成:rowkey+family+qualifier+type+timestamp
value的构成:字节形式存储

1.2.3 数据模型
在 HBase 表中,一条数据由一个唯一的键(RowKey)和多个列(Column)组成。多个列可以归属于同一个列族(Column Family)。同一个列族中的所有列的数据会存储在同一个 Store 中,这有助于提高数据的缓存和查询效率。HBase 的表是稀疏存储的,因此用户可以动态地添加列,不需要在创建表时预先定义所有列。
在数据库和数据存储中,稀疏(Sparse)指的是数据中包含大量的空值或缺失值。稀疏存储在设计上允许表中部分行不包含某些列的数据,这样就可以更高效地利用存储空间。
HBase 中的数据按行键(RowKey)排序,同时,HBase 会根据 RowKey 的范围将表拆分为多个 Region,并存储在不同的 RegionServer 上,以实现分布式存储和高效读取。

图示解释
整个表按照 RowKey 的字典顺序排序,数据被分成多个 Region,并且同一 Region 中的数据根据列族被分开存储在不同的 HFile 文件中。HBase 的这种数据存储方式有助于实现高效的分布式存储和快速的数据检索。图中展示了 Region、RowKey、Column Family 和 Cell 等核心概念之间的关系。
核心概念
NameSpace(命名空间):
定义:类似于数据库系统中的“数据库”概念,每个命名空间下可以包含多个表。HBase 默认提供了两个命名空间:
hbase(用于存放系统表)和default(用户默认使用的命名空间)。举例:如果没有指定,图中的表
user默认存储在default命名空间中。
Table(表):
定义:HBase 使用表来组织数据,表由行和列组成。在定义表时,只需要声明列族,而不需要预先定义具体的列。列可以在数据写入时动态添加,使 HBase 能够灵活应对数据结构的变化。
举例:图中的数据表
user就是一个 HBase 表,其中包含了personal和contact两个列族。
Region:
定义:Region 是 HBase 表的水平切片,负责存储一定范围的行数据。表的数据被分布到多个 Region 中,每个 Region 存储在一个 RegionServer 上,不会跨服务器分布。当表中的数据增多时,Region 会被拆分成两个新的 Region。
举例:图中展示了
Region1、Region2和Region3。每个 Region 负责存储一部分 RowKey 范围内的行数据,例如Region1负责RowKey从user-1到user-11的数据。
RowKey(行键):
定义:RowKey 是每行数据的唯一标识符,数据按 RowKey 的字典顺序存储。查询数据时主要通过 RowKey 进行检索,因此设计合适的 RowKey 对于性能非常重要。
举例:在图中,
RowKey列展示了各行的唯一标识符,如user-1,user-2等。数据按照RowKey的顺序从上到下排列。
Column Family(列族):
定义:列族是 HBase 数据存储的物理单位,每个列族可以包含多个列。在创建表时,列族必须指定,列族数量不宜过多(建议每个表不超过 3 个列族)。同一个列族的数据会被存储在一起。
举例:图中展示了两个列族:
personal和contact。personal列族包含了name、gender和age列,contact列族包含了phone和address列。
Column(列):
定义:每个列由列族(Column Family)和列限定符(Column Qualifier)确定。列可以动态添加,不需要在表创建时预定义。
举例:在图中,
personal:name和contact:phone是具体的列。name和phone分别属于不同的列族。
TimeStamp(时间戳):
定义:时间戳用于标识数据的不同版本。每次写入数据时,系统会自动生成一个时间戳,除非用户手动指定。这样同一个单元格可以保存多个版本的数据。
举例:虽然图中没有直接展示时间戳,你可以想象每个
Cell都有多个时间版本,记录了不同时间点的数据更新。
Cell(单元格):
定义:Cell 是 HBase 中的最小数据存储单元,由
{RowKey, Column Family: Column Qualifier, TimeStamp}唯一确定。单元格中的数据以字节数组形式存储,没有固定的类型。举例:图中每一个小方格代表一个
Cell。例如,在user-6的personal:name单元格中,存储了名字为吴十的数据。
1.3HBase架构
1.3.1 HBase 的基本架构

基于图的 HBase 架构解释
HMaster:HBase 集群中的管理者,负责监控和管理整个集群。它分配和管理数据的分片(称为“Region”),并确保数据在多个服务器上正确分布和备份。可以理解为集群的“指挥官”。
Region Server:HBase 中用于存储和管理数据的工作者。每个 Region Server 负责存储特定范围的数据(即多个 Region),并处理对这些数据的读写请求。Region Server 是数据的实际“仓库”,负责让数据可以被快速访问。
客户端请求:客户端发送一个数据读写请求,可能首先联系 HMaster 来确定数据所在的 Region Server。
HMaster 定位:HMaster 确定数据所在的 Region Server,并告诉客户端。【HMaster 是 HBase 集群的主控节点】
数据操作:客户端直接与相应的 Region Server 通信,进行数据的读写操作。【Region Server 是 HBase 中的工作节点,负责实际的数据存储和处理。每个 Region Server 管理一个或多个 Region。】
ZooKeeper 协调:ZooKeeper 监控集群各个组件的状态,确保集群的稳定性。
数据存储:Region Server 最终将数据存储在 HDFS 的 DataNode 上。
1.3.2 HBase 的核心架构
HBase 的核心架构由以下五个部分组成:HBase Client、HMaster、Region Server、ZooKeeper 和 HDFS。这些组件一起协同工作,构成了 HBase 的分布式数据存储系统。
它的架构组成如下图所示。


图示解读
图中展示了 HBase 的各个核心组件及其相互关系:
Client 通过 HMaster 定位数据并与 Region Server 交互。
Region Server 管理多个 Region,每个 Region 由多个 Store 组成。
Store 包含 MemStore(内存存储)和 StoreFile(持久化存储,底层为 HFile)。
HMaster 和 Region Server 的状态和操作由 ZooKeeper 协调管理,数据最终存储在 HDFS 中。
各组件的涵义
1. HBase Client
作用:HBase Client 是用户与 HBase 交互的接口。通过它,用户可以查询、插入或删除数据。
工作流程:Client 会通过 HMaster 定位数据所在的 Region Server,并与它进行数据操作。
2. HMaster
作用:HMaster 是 HBase 的主节点,负责管理整个集群。
职责:
分配和管理 Region Server,确保负载均衡。
管理 Region 的分裂和迁移。
维护集群的元数据,处理表的创建、删除和修改。
在 Region Server 出现故障时,协调故障恢复。
3.RegionServer
作用:Region Server 是 HBase 集群中的工作节点,负责实际的数据存储和处理。
职责:
管理一个或多个 Region(表的一部分数据)。
处理数据的读写请求。
当 Region 数据增多时,进行分裂操作。
Region:
定义:Region 是表的一部分数据,包含一定范围的 RowKey。
结构:Region 包含多个 Store,每个 Store 对应一个列族(Column Family)
如下图所示。一个 Region Server 是包含多个 Region 的,这里仅展示一个。

Store:
定义:一个 Region 包含多个 Store,每个 Store 对应一个列族。Store 是存储某个列族数据的单元,由 MemStore 和 StoreFile 组成。
每个 Store 包含 MemStore(内存中的数据)和 StoreFile(磁盘中的数据),数据首先进入 MemStore,之后再被持久化为 StoreFile。
MemStore:数据先写入内存中的 MemStore,达到一定阈值后再写入磁盘中的 StoreFile。
StoreFile:持久化存储数据的文件,底层为 HFile 格式。
StoreFile(HFile):
定义:HFile 是 StoreFile 在 HDFS 中的实际存储文件。
HLog:
作用:记录数据操作的日志,当出现故障时,可以通过日志重放恢复数据。
4. ZooKeeper
HMaster高可用
存放整个 HBase集群的
元数据以及集群的状态信息;实现HMaster主从节点的failover故障转移。
1.4 一图看懂Hbase数据存储
表1:数据在 RDBMS 中的排布示例

表2:数据在 HBase 中的排布(逻辑结构:指一个文件在用户面前所呈现的形式,数据之间的相互关系。)

表3:数据在 HBase 中的排布(物理结构:指文件在文件存储器上的存储形式)

图4:Hbase 中逻辑上数据的排布与物理上排布的关联


上图我们看到数据分布在两个 CF 中,并且每个 CF 对应一个 HFile。并且逻辑上每一行中的一个单元格数据,对应于 HFile 中的一行;
然后当用户按照 Row-key 查询数据的时候,HBase 会遍历两个 HFile,通过相同的 Row-Key 标识,将相关的单元格组织成行返回,这样便有了逻辑上的行数据。
图5:行存储和列存储数据读取过程

优化后的示例包含了对 HBase 数据存储机制的更详细解释和具体示例,并补充了一些说明以便于理解。以下是经过优化后的内容:
二、安装并配置HBase2.2.3
2.1 HBase环境准备
HBase的运行有三种模式:单机模式、伪分布式模式、分布式模式。
单机模式:在一台计算机上安装和使用HBase,不涉及数据的分布式存储;
伪分布式模式:在一台计算机上模拟一个小的集群;
分布式模式:使用多台计算机实现物理意义上的分布式存储。
本教程运行环境
centos7
JDK1.8 (配置好环境变量)
Hadoop3.1.3 (配置好环境变量)
zeeKeeper集群
Hbase-2.2.3
下载地址HBase下载地址
hbase-2.2.3-bin.tar.gz
2.2 HBase2.2.3安装
完全分布式配置
一、集群规划(Hbase HA)
HBase 集群搭建与高可用配置
在本次配置中,我们将搭建一个由 3 个节点组成的 HBase 集群,配置如下:
1.Region Server 部署:
三台主机(
master、slave1、slave2)上均部署Region Server【存储和管理数据】,负责管理和存储 HBase 表的数据。
2.HMaster 服务配置:
在
master节点上部署主HMaster服务,负责管理整个 HBase 集群。为了保证集群的高可用性,在
slave1节点上部署备用HMaster服务。
3.高可用管理:
HMaster服务由ZooKeeper集群进行协调管理。如果主HMaster(部署在master节点上)出现故障或不可用,ZooKeeper将自动切换到slave1上的备用HMaster,使其成为新的主HMaster,确保集群的持续可用性。
这种架构能够有效提升 HBase 集群的可靠性和稳定性,在主节点发生故障时,集群可以迅速恢复并继续提供服务。

二、前置条件
HBase 的运行需要依赖 Hadoop集群 和 JDK(HBase 2.0+ 对应 JDK 1.8+) 。同时为了提升 HBase 集群的高可用性和稳定性,这里我们不采用 HBase 内置的 Zookeeper 服务,而采用外置的 Zookeeper 集群。相关搭建步骤可以参阅:
Linux 环境下 JDK 安装
Zookeeper 集群环境搭建
Hadoop 集群环境搭建
三、集群搭建
3.1 下载并解压
下载地址HBase下载地址
下载hbase-2.2.3-bin.tar.gz文件到本地/opt/software。
解压安装包
hbase-2.2.3-bin.tar.gz至路径/opt/apps,命令如下:
cd /opt/software
tar -zxvf hbase-2.2.3-bin.tar.gz -C /opt/apps将解压的文件名hbase-2.2.3改为hbase,以方便使用,命令如下:
cd /opt/apps
mv ./hbase-2.2.3 ./hbase3.2 配置hbase-env.sh
vi /opt/apps/hbase/conf/hbase-env.sh
修改配置如下:
# 设置 Java 的安装路径,HBase 需要依赖 Java 环境来运行
export JAVA_HOME=/opt/apps/jdk
# 将 Hadoop 的配置文件路径加入到HBase的类路径中,使得HBase可以正确读取Hadoop配置,如core-site.xml和 hdfs-site.xml。
export HBASE_CLASSPATH=/opt/apps/hadoop/etc/hadoop
# 禁用 HBase 自动查找 Hadoop 的类路径,确保 HBase 使用其自带的库和配置,避免可能的类路径冲突
export HBASE_DISABLE_HADOOP_CLASSPATH_LOOKUP="true"
# 不使用内置的zookeeper服务(Hbase自带有zookeeper,建议用我们自己搭建的zookeeper)
export HBASE_MANAGES_ZK=false
# 设置本地库路径,以便 HBase 可以使用 Hadoop 的本地库进行优化,例如使用本地的 native 库来加速操作
export LD_LIBRARY_PATH=/opt/apps/hadoop/lib/native3.3 配置hbase-site.xml
编辑配置文件
cd /opt/apps/hbase/conf
vi hbase-site.xml
# 如果vi不方便复制下面的配置文件,双击用编辑器打开进行粘贴<configuration>
<!-- 指定 HBase 数据在 HDFS 上的存储路径。路径中的端口号要与 hdfs-site.xml 中的配置保持一致 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://master:9000/hbase</value>
</property>
<!-- 指定 HBase 以分布式模式运行 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<!-- 指定 ZooKeeper 集群节点的地址列表,通常用于 HBase 和 ZooKeeper 的连接 -->
<name>hbase.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
<!--
禁用 HBase 对 HDFS 流功能的强制检查。
如果设置为 false,HBase 将不再严格检查 HDFS 流能力,这对于一些不完全兼容 HDFS 的文件系统(如本地文件系统或云存储)有帮助。
此配置可以在测试环境中解决 HMaster 启动时 WAL(Write-Ahead Log)初始化失败的问题,但在生产环境中应谨慎使用。
-->
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
<!-- HBase 临时文件路径-->
<property>
<name>hbase.tmp.dir</name>
<value>/opt/apps/hbase/data/tmp</value>
</property>
</configuration>在 master 节点创建 HBase 用于存放临时文件的目录
# 在 master 节点创建 hbase.tmp.dir 目录,与配置文件一致
mkdir -p /opt/apps/hbase/data/tmp3.4 配置regionservers
作用:指定HBase集群中的Region Server节点,负责存储和管理HBase表的数据。
cd /opt/apps/hbase/conf
vi regionservers
# 配置以下内容
master
slave1
slave23.5 配置backup-masters
作用:创建back-masters配置文件,实现HMaster的高可用
cd /opt/apps/hbase/conf
vi backup-masters
# 配置以下内容
slave1backup-masters 这个文件是不存在的,需要新建,主要用来指明备用的 master 节点,可以是多个。
3.6 三台机器添加HBASE_HOME的环境变量
# 依次在三台电脑中操作
vi /etc/profile
# 在配置文件最后键入如下信息:
# Hbase
export HBASE_HOME=/opt/apps/hbase
export PATH=$PATH:$HBASE_HOME/bin
# 让配置文件立即生效
source /etc/profile
echo $PATH3.7 安装目录分发
将Master节点上的HBase 的目录分发到Slave1/Slave2主机
scp -r /opt/apps/hbase slave1:/opt/apps/
scp -r /opt/apps/hbase slave2:/opt/apps/四、启动集群
4.1 启动ZooKeeper集群
# 在Master/Slave1/Slave2主机上分别启动 ZooKeeper 服务
zkServer.sh start
# 在Master/Slave1/Slave2主机上分别检查 ZooKeeper 状态
zkServer.sh status
4.2 启动Hadoop集群
# 在master启动dfs服务
start-dfs.sh
# 在slave1启动yarn服务
start-yarn.sh4.3 启动HBase的HA集群
# 在master启动HBase
start-hbase.sh验证:
## 查看各主机的进程
# master
hadoop@master:~$ jps
20435 Jps
19220 NodeManager
19817 HRegionServer
18442 NameNode
19676 HMaster
18670 DataNode
17790 QuorumPeerMain
# slave1
hadoop@slave1:~$ jps
27472 NodeManager
27636 ResourceManager
28357 HMaster
28968 Jps
28233 HRegionServer
27178 DataNode
26602 QuorumPeerMain
# slave2
hadoop@slave2:~$ jps
18946 NodeManager
18743 SecondaryNameNode
19400 HRegionServer
17993 QuorumPeerMain
18540 DataNode
20078 Jps4.4 WEB端查看界面
http://master:16010


slave1上的 HBase 出于备用状态:

三、 编程实践
## 1.启动zookeeper集群
# 三台服务器上分别启动 ZooKeeper 服务:
zkServer.sh start
# 三台服务器上分别检查 ZooKeeper 状态:
zkServer.sh status
## 2.启动Hadoop集群
# 在master启动dfs服务
start-dfs.sh
# 在slave1启动yarn服务
start-yarn.sh
## 3.启动Hbase集群
# 在master启动HBase
start-hbase.shHBase Shell
HBase Shell支持的命令。
DML(data manipulation language 数据操纵语言):
它们是增、删、改、查SELECT、UPDATE、INSERT、DELETE,对数据库里的数据进行操作的语言
DDL(data definition language 数据定义语言):
主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等初始化工作上,他们大多在建立表时使用

3.1 实验一
实验目标:
熟悉 HBase 基本操作:
理解命名空间和表的管理:
掌握数据操作命令:
熟悉数据更新和删除操作:
理解 HBase 与 HDFS 的交互:
使用 Web UI 管理界面:
深入理解 HBase 数据模型:
实验步骤:
3.1.1 基本操作
1. 进入 HBase 客户端命令行
hbase shell
2. 查看当前操作用户:
whoami
3.查看服务器状态信息
status
4. 查看命名空间列表
hbase(main):010:0> list_namespace
# 运行结果
NAMESPACE
default
hbase
2 row(s)
Took 0.0969 seconds
# 在HBase中,命名空间(namespace)是用于逻辑上隔离和组织表的一种方式,类似于关系型数据库中的数据库概念。
`HBase系统默认定义了两个缺省的namespace
default:
这是 HBase 中的默认命名空间。当用户创建表而不指定特定的命名空间时,这些表会被自动放入 default 命名空间中。
举例来说,如果你创建一个名为 mytable 的表而不指定命名空间,那么它会被创建为 default:mytable。
hbase:
这是一个系统命名空间,用于存储 HBase 内部使用的一些表,比如 hbase:meta 表。
hbase:meta 表存储了 HBase 中所有表的元数据信息,比如表的结构、区域信息等。5.创建命名空间ods
create_namespace 'ods'
6.显示指定命名空间中所有的表
hbase(main):008:0> list_namespace_tables 'hbase'
# 运行结果:
TABLE
meta
namespace
2 row(s)
Took 0.0265 seconds
=> ["meta", "namespace"]3.1.2 表的操作
与关系型数据库不同,在Hbase中,基本组成为表,不存在多个数据库。因此,在 HBase 中存储数据先要创建表,创建表的同时需要设置列族的数量和属性。
Hbase表结构

1. 创建表
注意:在 HBase Shell 语法中,所有字符串参数都必须包含在单引号中,且区分大小写,如 Student 和 student 代表两个不同的表。
# 创建student表和列族info【并指定数据可以保留最近的 3 个版本】
// 表名 列族1
hbase(main):003:0> create 'student', {NAME => 'info', VERSIONS => 3}
# 运行结果
Created table student
Took 1.2936 seconds
=> ["student"]HBase 默认的命名空间为 default,这条命令创建了名为 Student 的表,表中包含1个列族info。
另外,在上条命令中没有对列族参数进行定义,因此使用的都是默认参数,如果建表时要设置列族的参数,参考以下方式:
create 'student', {NAME => 'info', VERSIONS => 3}, {NAME =>'grades', BLOCKCACHE => true}
这条命令创建了名为 Student 的表,表中包含两个列族,分别为 info 和 grades。
大括号内是对列族的定义,NAME、VERSION 和 BLOCKCACHE 是参数名,无须使用单引号,符号=>表示将后面的值赋给指定参数。例如,VERSIONS => 3是指此单元格内的数据可以保留最近的 3 个版本,BLOCKCACHE => true指允许读取数据时进行缓存。
2. 查看hbase当中存在的表
# 返回当前 HBase 实例中所有表的名称。包括不同命名空间下的所有表
list3.插入数据到表
在 HBase 中,添加数据时系统会自动为每条数据生成一个时间戳,用于版本控制。因此,当需要修改某个单元格的数据时,只需直接添加新的数据,HBase 会自动创建一个新的版本,完成“改”操作,而旧的版本仍然保留。系统会定期进行垃圾回收,默认只保留最新的几个版本,具体的保留版本数可以在创建表时通过设置 VERSIONS 参数来指定。
HBase中用put命令添加数据
put '表名', '行键', '列族:列', '值'
注意:
1.每次 put 操作只能为表中的一个单元格(即一行中的某一列)插入数据,因此直接通过 Shell 命令插入数据效率较低。在实际应用中,通常通过编程接口(如 Java API)进行批量操作,以提高数据插入的效率。。
2.HBase 表中的 行键(RowKey) 是用户自定义的唯一标识符,在 put 命令中必须显式指定。例如
# 表名 rowkey 列族:字段名 值
hbase(main):003:0> put 'student', '1001', 'info:name', 'Tom'
0 row(s) in 0.0160 seconds
hbase(main):004:0> put 'student', '1001', 'info:sex', 'male'
0 row(s) in 0.3020 seconds
hbase(main):005:0> put 'student', '1001', 'info:age', '20'
0 row(s) in 0.0330 seconds
hbase(main):006:0> put 'student', '1002', 'info:name', 'Lisa'
0 row(s) in 0.0160 seconds
hbase(main):007:0> put 'student', '1002', 'info:sex', 'female'
0 row(s) in 0.0220 seconds
hbase(main):008:0> put 'student', '1002', 'info:age', '18'
0 row(s) in 0.0160 seconds4.把数据写入HDFS
此时由于数据还在内存中,所以hdfs上查看不到,可以人为将数据溢写到hdfs
方法一:强制写入
# 强制将 MemStore 中的数据写入 HDFS
hbase(main):002:0> flush 'student'方法二:合并文件(系统一般会自动合并 当到达一定数量)
# # 进行 major 合并操作
hbase(main):003:0> major_compact 'student' 
## Hbase的storeFile(compact)合并机制
指的memStore中不断进行flush刷新操作, 就会产生多个storeFile的文件, 当storeFile的文件达到一定阈值后, 就会触发compact的合并机制, 将多个storeFile合并为一个大的HFile文件
阈值: 达到3个及以上
--minor :
作用: 将多个小的storeFile合并为一个较大的Hfile操作
##阈值: 达到3个及以上
注意: 此合并过程, 仅仅将多个合并为一个, 对数据进行排序操作, 如果此时数据有过期, 或者有标记为删除数据, 此时不做任何的处理 (类似于 内存合并中基础型),所以说, 此合并操作, 效率比较高
--major:
作用: 将较大的HFile 和 之前的大的Hfile进行合并形成一个更大的Hfile文件 (全局合并)
##阈值: 默认 7天
注意: 此合并过程, 会将那些过期的数据, 或者已经标记删除的数据, 在这次合并中, 全部都清除掉5.查看HDFS的webUI
# 在浏览器中输入URL
192.168.36.100:9870
如果点开上图中的文件会看到乱码:是因为这些数据是以 HBase 的 HFile 文件格式存储的。这种文件格式并不是纯文本,它包含了二进制编码的数据,并且经过压缩和编码,以便在 HBase 中高效地存储和读取。因此,直接查看 HFile 文件的内容会看到许多不可读的字符和乱码。
要正确读取和查看 HFile 文件的内容,通常需要使用 HBase 提供的工具或通过 HBase API 来解码和解析数据,这样才能看到实际的存储内容。
6.查看HBase的Web UI管理界面
在Tables中可以看到用户自定义的表格信息

7.查看hdfs文件中的数据
# 使用 hbase hfile 工具来查看 HBase 数据中的 HFile 文件内容
[root@master ~]# hbase hfile -p -f /hbase/data/default/student/85c2594d3638afe0d697106adc2e65c3/info/f5920b9920db4e8cbb373c38febeeff4# 运行结果
2022-12-03 20:45:06,329 WARN [main] util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
2022-12-03 20:45:08,163 INFO [main] metrics.MetricRegistries: Loaded MetricRegistries class org.apache.hadoop.hbase.metrics.impl.MetricRegistriesImpl
K: 1001/info:age/1670071231712/Put/vlen=2/seqid=25 V: 20
K: 1001/info:name/1669039547140/Put/vlen=3/seqid=0 V: Tom
K: 1001/info:sex/1670070021029/Put/vlen=4/seqid=21 V: male
K: 1002/info:age/1670071259900/Put/vlen=2/seqid=28 V: 18
K: 1002/info:name/1670071244363/Put/vlen=4/seqid=26 V: Lisa
K: 1002/info:sex/1670071252272/Put/vlen=6/seqid=27 V: female
Scanned kv count -> 6解释:
HBase 中存储的数据项为 "键值对(Key-Value)"
K: <rowKey>/info:<columnQualifier>/<timestamp>/Put/vlen=<length>/seqid=<sequenceId>表示 HBase 数据的存储格式。
1001:行键(Row Key),表示学生的唯一标识。
info:age:列族和列限定符,这里表示age列。
1670071231712:时间戳,代表该数据插入的时间。
Put:操作类型,表示数据写入方式为插入(Put)。
vlen=2:值长度,这里表示age的值长度为 2。
seqid=25:HBase 的序列号,用于版本控制。
8. 扫描查看表数据
语法:
scan命令:用于扫描表中的多行数据。
scan '<table_name>', {STARTROW => '<start_row_key>', STOPROW => '<stop_row_key>', COLUMNS => ['<column_family:column_qualifier>'], LIMIT => <limit>, VERSIONS => <num_versions>}get命令:用于检索特定行的数据;
# 获取指定表中特定行的指定列数据【即某单元格的数据】
get '<table_name>', '<row_key>', '<column_family:column_qualifier>'
# 获取指定表中特定行的所有列数据
get '<table_name>', '<row_key>'
# 8.1 查询表中所有的记录
hbase(main):010:0> scan 'student'
# 运行结果
ROW COLUMN+CELL
1001 column=info:name, timestamp=1669035441666, value=Tom
1001 column=info:age, timestamp=1669035432878, value=20
1001 column=info:sex, timestamp=1669035423148, value=male
1002 column=info:age, timestamp=1669035472710, value=18
1002 column=info:name, timestamp=1669035441514, value=Lisa
1002 column=info:sex, timestamp=1669035466152, value=female
2 row(s)
Took 0.0772 seconds
# 2 row(s) 表示表中有2行数据【以行键来区分】
# 8.2 扫描名为 'student' 的表,仅返回行键为 '1001' 的行
hbase(main):011:0> scan 'student',{STARTROW => '1001',STOPROW => '1001'}
# 运行结果
ROW COLUMN+CELL
1001 column=info:name, timestamp=1669035441666, value=Tom
1001 column=info:age, timestamp=1669035432878, value=20
1001 column=info:sex, timestamp=1669035423148, value=male
1 row(s)
# 8.3 扫描名为 'student' 的表,从指定的行键 '1001' 开始
hbase(main):021:0> scan 'student',{STARTROW => '1001'}
# 运行结果
ROW COLUMN+CELL
1001 column=info:name, timestamp=1669035441666, value=Tom
1001 column=info:age, timestamp=1669035432878, value=20
1001 column=info:sex, timestamp=1669035423148, value=male
1002 column=info:age, timestamp=1669035472710, value=18
1002 column=info:name, timestamp=1669035441514, value=Lisa
1002 column=info:sex, timestamp=1669035466152, value=female
2 row(s)
# 8.4 扫描名为 'student' 的表,仅返回列族 'info' 下的列 'name' 的数据
hbase(main):030:0> scan 'student',{COLUMN=>'info:name'}
# 运行结果
ROW COLUMN+CELL
1001 column=info:name, timestamp=1669039547140, value=Tom
1002 column=info:name, timestamp=1669035441514, value=Lisa
2 row(s)
# 8.5 查看多列的数据
hbase(main):030:0> scan 'student', {COLUMNS => ['info:name', 'info:age']}
# 运行结果
ROW COLUMN+CELL
1001 column=info:age, timestamp=1731038024852, value=20
1001 column=info:name, timestamp=1731038007966, value=Tom
1002 column=info:age, timestamp=1731038048176, value=18
1002 column=info:name, timestamp=1731038031761, value=Lisa
2 row(s)
Took 0.0145 seconds
# 8.6 扫描名为"student"表中的"info:name"和"info:age"列,并限制结果返回前1行数据。
hbase(main):030:0> scan 'student', {COLUMNS => ['info:name', 'info:age'], LIMIT => 1}
# 运行结果
ROW COLUMN+CELL
1001 column=info:age, timestamp=1731038024852, value=20
1001 column=info:name, timestamp=1731038007966, value=Tom
1 row(s)
Took 0.0204 seconds
# 8.7 扫描名为 'student' 的表,仅返回列族 'info' 中的所有列的数据
hbase(main):031:0> scan 'student',{COLUMN=>'info'}
# 运行结果
ROW COLUMN+CELL
1001 column=info:age, timestamp=1669039580183, value=25
1001 column=info:name, timestamp=1669039547140, value=Tom
1001 column=info:sex, timestamp=1669035423148, value=male
1002 column=info:age, timestamp=1669035472710, value=18
1002 column=info:name, timestamp=1669035441514, value=Lisa
1002 column=info:sex, timestamp=1669035466152, value=female
2 row(s)
# 8.8 范围查询:STARTROW开始行,LIMIT=>1 取一条数据,VERSIONS=1 查询最新版本
hbase(main):032:0> scan 'student',{STARTROW=>'1001',LIMIT=>1,VERSIONS =>1}
# 运行结果
ROW COLUMN+CELL
1001 column=info:age, timestamp=1731038024852, value=20
1001 column=info:name, timestamp=1731038007966, value=Tom
1001 column=info:sex, timestamp=1731038016758, value=male
1 row(s)
Took 0.0118 seconds 9. 查看表结构和列族信息
hbase(main):022:0> desc 'student'
# 运行结果
Table student is ENABLED
student
COLUMN FAMILIES DESCRIPTION
{NAME => 'info', VERSIONS => '3', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS =>
'FALSE', CACHE_DATA_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLICATIO
N_SCOPE => '0', BLOOMFILTER => 'ROW', CACHE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'fal
se', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'} Table Status:
Table student is ENABLED表示表student当前是启用状态,可以读写数据。Column Families:
NAME => 'info': 该表只有一个列族info。列族在 HBase 中用于将表的列分组,每个列族有多个列。VERSIONS:
3表示每个单元格保留三个版本的数据,可以查看历史数据。
10. 更新指定字段的数据
# 查看表 student 中行键为 1001的全部数据。
hbase(main):023:0> get 'student', '1001' # 表名 + rowkey
# 运行结果
COLUMN CELL
info:age timestamp=1731038024852, value=20
info:name timestamp=1731038007966, value=Tom
info:sex timestamp=1731038016758, value=male
# 如果行键和列(例如'1001'和'info:name')已存在,put 命令会更新该列的值
hbase(main):023:0> put 'student','1001','info:name','Mark'
hbase(main):024:0> put 'student','1001','info:age','25'
# 查看修改后的数据
hbase(main):023:0> get 'student', '1001'
# 运行结果
COLUMN CELL
info:age timestamp=1731038024852, value=25
info:name timestamp=1731038007966, value=Mark
info:sex timestamp=1731038016758, value=male
11. 查看指定"行”或 指定“列族:列”的数据
# 11.1 查看指定"行"的数据
hbase(main):025:0> get 'student','1001' # 表名 + rowkey
# 运行结果
COLUMN CELL
info:age timestamp=1669039580183, value=25
info:name timestamp=1669039547140, value=Tom
info:name timestamp=1669039548888, value=Mark
info:sex timestamp=1669035423148, value=male
1 row(s)
# 11.2 查看指定"行"+"列族:列"的数据
#表名 + rowkey + 列簇:字段名
hbase(main):026:0> get 'student','1001','info:name'
# 运行结果
COLUMN CELL
info:name timestamp=1669039547140, value=Tom
info:name timestamp=1669039548888, value=Mark12. 统计表数据行数
hbase(main):027:0> count 'student'
# 运行结果
2 row(s)11. 删除数据
delete 用于删除一个单元格【列】的数据,是put的反向操作;
deleteall 操作用于删除一行数据。
# 删除某 rowkey 的某一列数据:【在 HBase 中,“单元格”是指具体的行键和列组合】
# 使用delete命令删除的是最新的版本的数据。
hbase(main):021:0> delete 'student','1001','info:sex'
# 查看数据
hbase(main):021:0> get 'student','1001'# 删除某 rowkey 的全部数据:
hbase(main):022:0> deleteall 'student', '1002'
# 查看表
hbase(main):022:0> scan 'student'12. 清空表数据
hbase(main):023:0> truncate 'student'
# 运行结果
Truncating 'student' table (it may take a while):
- Disabling table...
- Truncating table...提示:清空表的操作顺序为先 disable,然后再 truncate。
13. 删除表
# 13.1 首先需要先让该表为 disable 状态:
hbase(main):025:0> disable 'student'
# 13.2 然后才能 drop 这个表:
hbase(main):026:0> drop 'student'提示:如果直接 drop 表,会报错:ERROR: Table student is enabled. Disable it first.
14. 退出HBase数据库表操作
exit
3.2 实验二
实验目标
了解 HBase 的基本概念和结构。
学习 HBase 表的创建与列族设置。
学习如何向 HBase 表中插入、查询、更新和删除数据。
实验准备
HBase 集群已启动。
HBase Shell 已配置并可以使用。
实验步骤
1. 启动 HBase 集群并进入 HBase Shell
# 在Master/Slave1/Slave2主机上分别启动 ZooKeeper 服务
zkServer.sh start
# 在Master/Slave1/Slave2主机上分别检查 ZooKeeper 状态
zkServer.sh status
# 在master启动dfs服务
start-dfs.sh
# 在slave1启动yarn服务
start-yarn.sh
# 在master启动HBase
start-hbase.sh
# 进入 HBase Shell
hbase shell 2. 创建命名空间
在 HBase 中,可以通过命名空间来组织表。默认情况下,表存储在 default 命名空间中。可以创建自定义命名空间来分类存储表,例如创建一个 test 命名空间。
# 创建命名空间【数据库】
create_namespace 'test'
# 查看命名空间【数据库】
list_namespace3. 创建表
创建一个名为 students 的表,包含两个列族 info 和 scores,并指定版本数和缓存策略。
# 创建名为 'students' 的表,包含两个列族 'info' 和 'scores'
create 'test:students', {NAME=>'info',VERSIONS=>3}, {NAME=>'scores',BLOCKCACHE=>true}
# 查看所有表
list
# 或者查看指定的命名空间的表
list_namespace_tables 'test'解释:
info列族将存储学生的基本信息,如姓名、性别、年龄等。scores列族将存储学生的成绩信息。VERSIONS => 3表示保留每个单元格的 3 个数据版本。BLOCKCACHE => true表示开启数据缓存,以提高查询效率。
4. 插入数据
方法一:命令行插入数据
在 test:students 表中插入一些示例数据。数据以 put 命令插入,格式为 put '表名', '行键', '列族:列', '值'。
# 插入学生基本信息
put 'test:students', '1001', 'info:name', 'Alice'
put 'test:students', '1001', 'info:age', '20'
put 'test:students', '1001', 'info:gender', 'Female'
put 'test:students', '1002', 'info:name', 'Bob'
put 'test:students', '1002', 'info:age', '22'
put 'test:students', '1002', 'info:gender', 'Male'
# 插入学生成绩信息
put 'test:students', '1001', 'scores:math', '85'
put 'test:students', '1001', 'scores:english', '90'
put 'test:students', '1002', 'scores:math', '78'
put 'test:students', '1002', 'scores:english', '88'方法二:脚本插入数据
可以将这些 put 命令放到一个 HBase Shell 脚本中,然后通过 HBase Shell 执行该脚本。以下是具体步骤:
1) 创建 HBase Shell 脚本文件
创建一个文件,命名为 insert_students_data.hbase,内容如下:
put 'test:students', '1001', 'info:name', 'Alice'
put 'test:students', '1001', 'info:age', '20'
put 'test:students', '1001', 'info:gender', 'Female'
put 'test:students', '1002', 'info:name', 'Bob'
put 'test:students', '1002', 'info:age', '22'
put 'test:students', '1002', 'info:gender', 'Male'
put 'test:students', '1001', 'scores:math', '85'
put 'test:students', '1001', 'scores:english', '90'
put 'test:students', '1002', 'scores:math', '78'
put 'test:students', '1002', 'scores:english', '88'
put 'test:students', '1003', 'info:name', 'Charlie'
put 'test:students', '1003', 'info:age', '21'
put 'test:students', '1003', 'info:gender', 'Male'
put 'test:students', '1003', 'scores:math', '82'
put 'test:students', '1003', 'scores:english', '87'
put 'test:students', '1004', 'info:name', 'Daisy'
put 'test:students', '1004', 'info:age', '23'
put 'test:students', '1004', 'info:gender', 'Female'
put 'test:students', '1004', 'scores:math', '90'
put 'test:students', '1004', 'scores:english', '92'
put 'test:students', '1005', 'info:name', 'Edward'
put 'test:students', '1005', 'info:age', '20'
put 'test:students', '1005', 'info:gender', 'Male'
put 'test:students', '1005', 'scores:math', '76'
put 'test:students', '1005', 'scores:english', '85'
put 'test:students', '1006', 'info:name', 'Fiona'
put 'test:students', '1006', 'info:age', '22'
put 'test:students', '1006', 'info:gender', 'Female'
put 'test:students', '1006', 'scores:math', '88'
put 'test:students', '1006', 'scores:english', '91'
put 'test:students', '1007', 'info:name', 'George'
put 'test:students', '1007', 'info:age', '21'
put 'test:students', '1007', 'info:gender', 'Male'
put 'test:students', '1007', 'scores:math', '80'
put 'test:students', '1007', 'scores:english', '89'
put 'test:students', '1008', 'info:name', 'Hannah'
put 'test:students', '1008', 'info:age', '23'
put 'test:students', '1008', 'info:gender', 'Female'
put 'test:students', '1008', 'scores:math', '95'
put 'test:students', '1008', 'scores:english', '93'
put 'test:students', '1009', 'info:name', 'Ian'
put 'test:students', '1009', 'info:age', '20'
put 'test:students', '1009', 'info:gender', 'Male'
put 'test:students', '1009', 'scores:math', '78'
put 'test:students', '1009', 'scores:english', '84'
put 'test:students', '1010', 'info:name', 'Julia'
put 'test:students', '1010', 'info:age', '22'
put 'test:students', '1010', 'info:gender', 'Female'
put 'test:students', '1010', 'scores:math', '87'
put 'test:students', '1010', 'scores:english', '90'2) 复制文件
# 新开一个master节点的窗口,把insert_students_data.hbase文件先拖动到 ~家目录下
3) 运行 HBase Shell 脚本
[root@master ~]# hbase shell insert_students_data.hbase
注意事项
确保
test:students表已存在,否则在执行该脚本前需要先在 HBase 中创建该表。如果需要重复运行脚本,请注意数据会被更新,因为
put操作会插入新的版本数据。
5. 查询数据
5.1 查询整表数据
使用 scan 命令查看 test:students 表的所有数据。
scan 'test:students'
5.2 查询某列数据
使用 scan 命令查看 test:students 表的name列的所有数据。
scan 'test:students',{COLUMN=>'info:name'}
5.3 查询某列族数据
使用 scan 命令查看 test:students 表的info列族的所有数据。
scan 'test:students',{COLUMN=>'info'}
5.4 查询特定行数据
使用 get 命令查询某一行数据(例如行键为 1001 的数据)。
get 'test:students', '1001'
5.5 查询特定列数据
仅查询某行的特定列(例如查询行键为 1001 的学生的姓名)。
get 'test:students', '1001', 'info:name'
5.6 在 HDFS 中查看 HBase 表数据
# 进入 HDFS 并查看 HBase 数据目录
hdfs dfs -ls /hbase/data/test/students6. 更新数据
在 HBase 中更新数据的方式是直接插入新值,HBase 会为该单元格生成新的版本。例如,更改行键为 1001 的学生的 name 数据,并查看版本的变化 。
put 'test:students', '1001', 'info:name', 'linda'
put 'test:students', '1001', 'info:name', 'josn'
# 查看'1001'的'info:name'的多版本的数据
get 'test:students', '1001', 'info:name'
# 此时再更新一次数据,即第四个版本的数据,然后再使用get命令查看原第1版本的数据还在不在7. 删除数据
7.1 删除某行的特定列数据
使用 delete 命令删除特定行的某一列数据(例如删除行键为 1001 的学生的 gender 信息)。
delete 'test:students', '1001', 'info:gender'
# 注意:如果某列的数据有多个版本,默认是删除最新版本的数据7.2 删除整行数据
使用 deleteall 命令删除整行数据(例如删除行键为 1002 的学生数据)。
deleteall 'test:students', '1002'
8. 统计表数据行数
使用 count 命令统计表中数据行数。
count 'test:students'
9. 查看表结构
使用 describe 命令查看表的结构,包括列族配置等信息。
describe 'test:students'
10. 清空表数据
使用 truncate 命令清空表中的所有数据,但不删除表结构。
truncate 'test:students'
11. 删除表
在删除表之前需要先将其禁用,执行以下步骤删除表:
# 禁用表
disable 'test:students'
# 删除表
drop 'test:students'12. 删除命名空间
# 删除命名空间需要确保命名空间是空的,即其中没有任何表。
# 故在删除命名空间之前先要禁用并删除命名空间中的表
drop_namespace 'test'13. 退出 HBase Shell
完成实验后,可以退出 HBase Shell。
exit
实验总结
通过本实验,初学者可以掌握以下操作:
创建和删除命名空间、表。
插入、查询、更新和删除数据。
查看表结构、统计行数和清空数据。
这些基本操作是使用 HBase 的核心步骤,理解这些操作后,可以进一步通过 API 在编程中实现对 HBase 数据的操作。