一、HBase 简介
HBase 是一个分布式、可扩展的列式存储数据库,基于 Google 的 Bigtable 设计构建。它是 Hadoop 生态系统的一部分,主要用于处理海量的结构化数据。与传统的关系型数据库不同,HBase 采用列存储而不是行存储,这使得它非常适合处理大量的稀疏数据,并且支持快速随机访问。
1.1 HBase 的特点:
- 分布式架构:HBase 运行在集群模式下,数据被分布在多个节点上,实现了高可用性和容错能力。
- 横向扩展性:可以根据需求增加节点,扩展存储和计算能力。
- 列式存储:数据按照列而非行进行存储,这对某些特定应用(如大规模分析、实时数据访问)非常有利。
- 高并发写入:适合高吞吐量的数据写入和实时数据处理。
- 无模式(Schema-less):在 HBase 中,不同的行可以有不同的列,可以灵活地存储结构化或半结构化数据。
1.2 HBase 的用途:
- 大数据存储:当需要存储大量的数据并能够进行高效的快速查询时,HBase 是理想的选择。例如,可以用于存储日志数据、传感器数据、社交媒体数据等。
- 实时数据分析:HBase 支持快速的随机读写,适合需要实时分析的大数据场景,比如实时舆情监控、流量分析、金融风控等。
- 推荐系统:在需要处理大规模用户行为数据并进行实时推荐的应用中,HBase 可以用作数据存储后端。
- 社交媒体数据存储:像微博、Facebook、Twitter 等社交平台产生的庞大数据量,HBase 可以高效地存储和管理。
- 物联网(IoT)数据存储:随着设备数量增加,产生的数据量也是天文数字,HBase 能够有效地存储和查询这些设备数据。
1.3 HBase 原理架构
HBase 是基于分布式存储的,它的架构设计可以分为以下几个主要组件:
1.3.1 HBase 客户端
HBase 客户端用于与 HBase 系统进行交互,发起请求来读取或写入数据。客户端请求会经过以下组件进行处理。
1.3.2 Zookeeper
HBase 使用 Zookeeper 来协调集群中的各个节点,确保 HBase 的高可用性和一致性。Zookeeper 主要负责以下任务:
- 监控 HMaster:Zookeeper 监控 HBase 的主节点 HMaster 的状态,确保主节点出现故障时可以自动进行故障转移。
- 管理 RegionServer:Zookeeper 协调 RegionServer 节点之间的分布式操作,确保数据的负载均衡。
- Region 路由信息:存储每个 Region 的位置信息,客户端根据 Zookeeper 获取数据的存储位置。
1.3.3 HMaster
HMaster 是 HBase 集群中的主节点,负责管理整个集群的元数据和协调任务。HMaster 的主要职责包括:
- Region 分配:负责将 Region 分配到 RegionServer。
- Region 移动与负载均衡:根据 RegionServer 的负载情况,HMaster 会调整 Region 的分布,以确保负载均衡。
- 故障恢复:当 RegionServer 出现故障时,HMaster 会重新分配该节点上的 Region。
1.3.4 RegionServer
RegionServer 是 HBase 的工作节点,负责数据的读写操作。每个 RegionServer 负责处理一定数量的 Region。RegionServer 的主要功能包括:
- 读写请求处理:接收并处理客户端的读写请求。
- Region 存储与管理:每个 RegionServer 存储若干个 Region,每个 Region 代表 HBase 中一个数据分区。Region 会随着数据量的增加而被分割成多个子 Region。
- MemStore 与 HFile:在内存中,RegionServer 将写入的数据存储在 MemStore 中。数据经过一定时间后会被刷新到磁盘存储成 HFile 格式。
1.3.5 Region
Region 是 HBase 中数据的基本存储单元。每个 Region 存储一个数据范围,数据根据行键(Row Key)进行分区。每个 Region 内的数据按行键排序。当 Region 数据量增长到一定阈值时,Region 会进行分割,生成两个新的子 Region。
1.3.6 MemStore 和 HFile
HBase 内部将数据存储在 MemStore 和 HFile 中:
- MemStore:是内存中的数据缓存,用于临时存储客户端写入的数据。当 MemStore 达到一定大小时,会将数据写入磁盘上的 HFile。
- HFile:是存储在 HDFS 上的不可变文件,HFile 存储了持久化的 HBase 数据。HFile 是按时间顺序排序的,便于高效地进行读取和扫描。
1.3.7 HRegion
一个 HRegion 是 Region 的一个实例,它与 RegionServer 绑定。RegionServer 会存储若干个 HRegion,当 Region 达到设定的大小限制时,HBase 会对其进行分裂。
1.3.8 HBase WAL(Write-Ahead Log)
为了确保数据的可靠性,HBase 使用 WAL 日志(写前日志)。所有写入操作会首先写入 WAL 文件中,这样即使在写入数据到 MemStore 或 HFile 的过程中出现故障,也能够通过 WAL 恢复数据。
1.3.9 HBase 数据一致性
HBase 保证单行数据的一致性,这意味着对于同一行的多个版本,HBase 能够确保顺序的一致性。然而,对于跨行的事务处理,HBase 不支持多行事务的一致性。因此,HBase 更适合用于需要高吞吐量、低延迟读取的数据存储。
1.3.10 HBase 数据流程:
- 写数据:客户端向 RegionServer 发送写请求,数据先写入 MemStore,随后记录到 WAL 日志中。当 MemStore 达到阈值时,数据会被刷新到 HFile 文件中。
- 读数据:客户端请求数据时,RegionServer 会先检查 MemStore 中是否有该行数据,如果没有,查询 HFile。数据会被返回给客户端。
HBase 适用于需要高吞吐量、低延迟的场景,特别是对于实时写入、分析和查询海量数据的需求。
二、Zookeeper的安装
2.1 Zookeeper的下载
选择合适的Zookeeper版本下载
1 | wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/current/apache-zookeeper-3.9.3-bin.tar.gz |
2.2 Zookeeper的解压与重命名
解压下载完成的压缩包
1 | tar -zxvf apache-zookeeper-3.9.3-bin.tar.gz |
然后进行重命名
1 | mv apache-zookeeper-3.9.3-bin zookeeper-3.9.3 |
2.3 配置Zookeeper的环境变量
输入指令,打开文件夹
1 | sudo vim ~/.bashrc |
配置环境,输入以下变量
1 | export ZOOKEEPER_HOME=~/software/zookeeper-3.9.3 |
刷新环境变量
1 | source ~/.bashrc |
输入指令,检查是否成功配置
1 | echo $ZOOKEEPER_HOME |
最后分发环境变量
1 | xsync ~/.bashrc |
2.4 配置Master节点
进入Zookeeper的目录
1 | cd zookeeper-3.9.3/ |
创建data与logs目录
1 | mkdir data && mkdir logs |
指定当前节点的myid为1:创建myid,并在其中输入“1”
1 | vim zookeeper-3.9.3/data/myid |
创建zook.cfg文件
1 | cp zookeeper-3.9.3/conf/zoo_sample.cfg zookeeper-3.9.3/conf/zoo.cfg |
然后打开并修改
1 | vim zookeeper-3.9.3/conf/zoo.cfg |
修改内容如下
1 | dataDir=~/software/zookeeper-3.9.3/data |
然后分发Zookeeper到其它节点
1 | xsync zookeeper-3.9.3/ |
2.5 配置Slave节点
分别指定当前节点的myid为2个3:创建myid,并在其中输入“1”和“3”
1 | vim zookeeper-3.9.3/data/myid |
2.6 启动Zookeeper
在3个节点上启动Zookeeper
1 | ./zkServer.sh start |
然后分别输入,如果显示2个follower和1个leader,则说明启动成功
1 | ./zkServer.sh status |
2.7 Zookeeper集群启动脚本
进入home下的bin目录
1 | cd ~/bin/ |
输入指令,创建脚本
1 | vim zk.sh |
输入以下代码
1 |
|
保存退出后设置权限
1 | chmod 777 zk.sh |
三、Hbase的安装
3.1 Hbase的下载
首先确保已经安装并配置Hadoop,然后检查Hadoop版本是否与要下载的Hbase版本适配,然后在清华镜像源找到对应版本的下载地址,到虚拟机中的相关目录下下载安装包。
1 | wget https://mirrors.tuna.tsinghua.edu.cn/apache/hbase/2.5.10/hbase-2.5.10-bin.tar.gz |
随后输入指令进行解压
1 | tar -zxvf hbase-2.5.10-bin.tar.gz |
3.2 配置环境变量
输入指令,打开文件夹
1 | sudo vim ~/.bashrc |
配置环境,输入以下变量
1 | export HBASE_HOME=~/software/hbase-2.5.10 |
刷新环境变量
1 | source ~/.bashrc |
输入指令,检查是否成功配置
1 | echo $HBASE_HOME |
最后输入指令,查看Hbase版本
1 | hbase version |
3.3 配置模式
输出指令查看自己的Hadoop和Java的环境变量
1 | echo $HADOOP_HOME |
然后打开Hbase的环境文件
1 | vim hbase-2.5.10/conf/hbase-env.sh |
配置以下内容
1 | export HBASE_CLASSPATH=/home/ldy/software/hbase-2.5.10/conf |
然后打开hbase-site.xml文件
1 | vim hbase-2.5.10/conf/hbase-site.xml |
修改以下信息
- hbase.cluster.distributed 用于指定是否使用分布式集群模式
- 配置 hbase.rootdir 来指定数据的存储位置
- hbase.tmp.dir 用于指定 HBase 临时文件存储的目录。
- hbase.unsafe.stream.capability.enforce 控制是否强制检查流的能力,增加或减少系统的安全性。
1 | <configuration> |
3.4 启动测试
首先启动Hadoop集群与Zookeeper,然后输入指令启动Hbase
1 | $HBASE_HOME/bin/start-hbase.sh |
启动完成后,输入jps查看进程,出现以下信息,则说明Hbase运行了
HRegionServer 或 HMaster
3.5 Hbase集群脚本
创建脚本文件
1 | vim ~/bin/hbase.sh |
编写内容
1 |
|
设置权限
1 | chmod 777 ~/bin/hbase.sh |
四、 Hbase的基础操作
4.1 打开Hbase shell
输入以下指令打开Hbase shell
1 | hbase shell |
4.2 命名空间namespace
在 HBase 中,Namespace(命名空间) 是一种逻辑上的分区机制,用于对表进行分组和管理。它类似于关系数据库中的“数据库”概念,但 HBase 是一个分布式存储系统,Namespace 的作用更多是为了组织和管理表。
4.2.1 Namespace 的主要功能
表的分组: Namespace 可以将表按照功能、业务或项目进行分组,方便管理和维护。例如,一个公司可能会根据不同的业务部门创建不同的 Namespace,如“Finance”(财务部门)、“Sales”(销售部门)等。
权限控制: Namespace 提供了更细粒度的权限管理。管理员可以为不同的用户或用户组设置对特定 Namespace 的访问权限,从而控制对表的访问。
资源隔离: 虽然 HBase 是一个分布式存储系统,Namespace 在逻辑上可以将表分隔开,避免表之间的相互干扰,尤其是在多租户环境中,Namespace 可以隔离不同租户的数据。
简化管理: 通过 Namespace,管理员可以更方便地对表进行批量操作,例如批量删除、备份或恢复。
4.2.2 Namespace 的使用
默认 Namespace: HBase 默认有一个名为“default”的 Namespace。如果没有指定 Namespace,表会被创建在“default”中。
自定义 Namespace: 用户可以根据需要创建自定义的 Namespace。创建 Namespace 的命令如下:
1 | create_namespace 'school' |
查看 Namespace: 可以使用以下命令查看所有 Namespace:
1 | list_namespace |
删除 Namespace: 删除 Namespace:删除 Namespace 的命令如下,删除 Namespace 时,该 Namespace 下的所有表也会被删除,因此需要谨慎操作:
1 | drop_namespace 'school' |
4.3 表的操作
4.3.1 表的创建
假设我们要创建一个表 cat_table,包含两个列族:
- info:存储猫咪的基本信息,如名字、年龄、品种。
- owner:存储猫咪主人的信息,如名字和联系方式。
创建表的命令:
1 | create 'cat_table', 'info', 'owner' |
如果创建失败,显示
ERROR: org.apache.hadoop.hbase.ipc.ServerNotRunningYetException: Server is not running yet
at org.apache.hadoop.hbase.master.HMaster.checkServiceStarted(HMaster.java:3207)
at org.apache.hadoop.hbase.master.MasterRpcServices.isMasterRunning(MasterRpcServices.java:1163)
at org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos$MasterService$2.callBlockingMethod(MasterProtos.java)
at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:415)
at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:124)
at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:102)
at org.apache.hadoop.hbase.ipc.RpcHandler.run(RpcHandler.java:82)
For usage try 'help "create"'
则先退出hbase,然后关闭hadoop的安全模式
1 | hadoop dfsadmin -safemode leave |
继续建表,应该就能成功了。
4.3.2 表的查看
输入指令,可以查看当前有哪些表:
1 | list |
4.3.3 插入数据
假设我们有以下几只猫咪的数据:
-
猫咪1:
名字:Kimi
年龄:3岁
品种:英国短毛猫
主人:Alice
主人联系方式:1234567890 -
猫咪2:
名字:Tom
年龄:2岁
品种:橘猫
主人:Bob
主人联系方式:0987654321
则插入命令的指令为:
1 | put 'cat_table', 'cat1', 'info:name', 'Kimi' |
4.3.4 查询数据
1 | get 'cat_table', 'cat1' |
所得到的结果如下:
hbase:022:0> get 'cat_table', 'cat1'
COLUMN CELL
info:age timestamp=2025-02-18T14:38:30.289, value=3
info:breed timestamp=2025-02-18T14:38:30.334, value=British Shorthair
info:name timestamp=2025-02-18T14:38:30.200, value=Kimi
owner:contact timestamp=2025-02-18T14:38:32.701, value=1234567890
owner:name timestamp=2025-02-18T14:38:30.404, value=Alice
1 row(s)
Took 0.0866 seconds
hbase:023:0>
查询单只猫咪的特定信息(例如名字和品种):
1 | get 'cat_table', 'cat1', {COLUMN => 'info:name'} |
结果如下:
hbase:023:0> get 'cat_table', 'cat1', {COLUMN => 'info:name'}
COLUMN CELL
info:name timestamp=2025-02-18T14:38:30.200, value=Kimi
1 row(s)
Took 0.0276 seconds
hbase:024:0> get 'cat_table', 'cat1', {COLUMN => 'info:breed'}
COLUMN CELL
info:breed timestamp=2025-02-18T14:38:30.334, value=British Shorthair
1 row(s)
Took 0.0195 seconds
hbase:025:0>
查询所有猫咪的信息:
1 | scan 'cat_table' |
结果如下:
hbase:025:0> scan 'cat_table'
ROW COLUMN+CELL
cat1 column=info:age, timestamp=2025-02-18T14:38:30.289, value=3
cat1 column=info:breed, timestamp=2025-02-18T14:38:30.334, value=British
Shorthair
cat1 column=info:name, timestamp=2025-02-18T14:38:30.200, value=Kimi
cat1 column=owner:contact, timestamp=2025-02-18T14:38:32.701, value=12345 67890
cat1 column=owner:name, timestamp=2025-02-18T14:38:30.404, value=Alice
cat2 column=info:age, timestamp=2025-02-18T14:38:38.451, value=2
cat2 column=info:breed, timestamp=2025-02-18T14:38:38.500, value=Orange T abby
cat2 column=info:name, timestamp=2025-02-18T14:38:38.388, value=Tom
cat2 column=owner:contact, timestamp=2025-02-18T14:38:39.627, value=09876 54321
cat2 column=owner:name, timestamp=2025-02-18T14:38:38.541, value=Bob
2 row(s)
Took 0.0612 seconds
4.3.5 更新数据
假设 Kimi 的年龄变成了 4 岁:
1 | put 'cat_table', 'cat1', 'info:age', '4' |
查看数据,已经更新了:
hbase:028:0> get 'cat_table','cat1',{COLUMN => 'info:age'}
COLUMN CELL
info:age timestamp=2025-02-18T14:52:20.912, value=4
1 row(s)
Took 0.0118 seconds
4.3.6 删除数据
删除单个列(例如删除 Kimi 的主人联系方式):
1 | delete 'cat_table', 'cat1', 'owner:contact' |
删除整行数据(例如删除 Tom 的所有信息):
1 | deleteall 'cat_table', 'cat2' |
4.3.7 删除表
在删除表之前,需要先禁用表:
1 | disable 'cat_table' |
五、 Python API
5.1 导入hbase-python库
HappyBase 是一个用于与 Apache HBase 进行交互的 Python 客户端库,它提供了简单的 API 来执行对 HBase 的常见操作。
1 | pip install happybase |
可能会显示安装错误,需要安装 Microsoft C++ Build Tools,才能编译 C 扩展。
- 这时候需要进入 Microsoft C++ Build Tools 页面
- 点击 下载 按钮并运行安装程序
- 安装过程中,确保选择 C++ build tools 以及 Windows 10 SDK 组件。
- 完成安装后,重新启动计算机。
5.2 连接到 Hbase
1 | import happybase |
5.3 创建表
将创建一个包含猫咪数据的表。表的列族是 personal_info 和 health_info,其中包含猫咪的基本信息和健康数据。
1 | # 创建一个名为 "cats" 的表,包含两个列族:personal_info 和 health_info |
5.4 插入数据
插入一些猫咪的数据。假设我们有猫咪的基本信息(如名字、年龄、品种等)和健康信息(如体重、疫苗接种情况等)。
1 | table = connection.table(table_name) |
5.5 查询数据
查询某只猫咪的数据,可以使用 table.row() 方法根据 row_key 查询
1 | # 查询 cat1 的数据 |
产生的数据
Name: 啊啊
Age: 2
Breed: 黑猫
Weight: 4.5kg
Vaccinated: 已接种
5.6 扫描数据
扫描整个表并获取所有猫咪的信息,可以使用 table.scan() 方法:
1 | # 扫描表并打印所有猫咪的数据 |
结果如下
Row Key: b'cat1'
Data: {b'health_info:vaccinated': b'\xe5\xb7\xb2\xe6\x8e\xa5\xe7\xa7\x8d', b'health_info:weight': b'4.5kg', b'personal_info:age': b'2', b'personal_info:breed': b'\xe9\xbb\x91\xe7\x8c\xab', b'personal_info:name': b'\xe5\x95\x8a\xe5\x95\x8a'}
Row Key: b'cat2'
Data: {b'health_info:vaccinated': b'\xe6\x9c\xaa\xe6\x8e\xa5\xe7\xa7\x8d', b'health_info:weight': b'5kg', b'personal_info:age': b'1', b'personal_info:breed': b'\xe6\xa9\x98\xe7\x8c\xab', b'personal_info:name': b'\xe9\xa5\xb1\xe9\xa5\xb1'}
5.7 更新数据
更新已经存在的数据,例如修改 cat1 的体重信息:
1 | table.put(b'cat1', { |
5.8 删除数据
如果需要删除某个猫咪的数据,可以使用 table.delete():
1 | table.delete(b'cat2') # 删除 cat2 的数据 |
5.9 关闭连接
1 | connection.close() |
5.10 输出所有表内容
为了方便查看,编写一个输出表内所有数据的函数print_table_contents(connection,table_name)
1 |
|
5.11 表是否存在
根据传入的表名,查看是否存在该表
1 | def if_table_exists(connection,table_name): |