一、关于HBase
1、HBase是什么?
HBase的官网地址:https://hbase.apache.org/,其标志是一个漂亮的虎鲸。
官网对HBase的介绍非常直接:Apache HBase™ 是 Hadoop 数据库,一个分布式、可扩展的大数据存储引擎。
HBase的主要特征:
海量数据支持:支持数十亿行 × 数百万列的超大规模数据集。
高性能读写:在海量数据中可实现毫秒级的随机、实时读写操作。
深度Hadoop集成:基于HDFS进行文件持久化,继承了Hadoop强大的可扩展性(可基于廉价PC组建集群),并深度集成了MapReduce计算框架,正积极整合Spark。
强一致性(CP):从CAP理论看,HBase属于CP型,避免了脏读、幻读等最终一致性问题。
高性能与高活跃度:框架性能高效,开源社区活跃,其性能经过Facebook等大型商业产品验证(Facebook消息流转基础设施就构建于HBase之上)。
可以说,Hadoop + HBase共同提供了强悍的性能,支撑起整个大数据技术体系,如同操作系统为上层应用提供了基础。
技术渊源:Google的三篇论文
2003年:Google File System (GFS),可扩展的分布式文件系统。
2004年:MapReduce,大数据分布式计算框架。
2006年:BigTable,构建于GFS和MapReduce之上的多维稀疏图管理工具。
这三篇论文引发了开源大数据热潮:GFS启发了HDFS,MapReduce成为海量数据处理标准,两者结合形成Hadoop;BigTable启发了无数NoSQL数据库,而HBase正是继承了BigTable的正统思想。因此,Hadoop + HBase 模拟了Google处理海量网页的三大基石,成为开源大数据处理的基石。
2、HBase的数据结构
HBase虽然也有表、列的逻辑概念,但本质上是基于键值对(K-V)的方式存储数据,与传统关系型数据库区别很大。
其核心数据结构包含以下几个层级:
RowKey(行键):检索记录的唯一主键,按字典序排序存储。
Column Family(列簇):列的组,表定义时需指定。一个表不宜有过多列簇(建议1-3个)。
Column(列):属于某个列簇,列名以
列簇:列名(如info:name)的形式访问。列是动态扩展的,数据以字节码形式存储。Cell(单元格):由
{RowKey, Column Family:Column, Version}唯一确定的数据存储单元。Timestamp(时间戳):数据的版本标识,默认由写入时间决定,降序排列。
3、HBase的基础架构
HBase架构主要包含以下组件:
HMaster:负责管理RegionServer、分配Region、负载均衡、元数据管理(表增删改)等。
RegionServer:负责具体数据的读写请求,管理一系列Region。
Region:表数据的横向分片,当表数据量大时,一张表会被水平拆分成多个Region,分布到不同RegionServer上。
Store:一个Region按列簇划分为多个Store。
MemStore:写缓存。数据先写入内存中的MemStore,排序后达到刷写条件时才持久化到StoreFile。
StoreFile (HFile):实际存储数据的物理文件,保存在HDFS上。
WAL (Write-Ahead Log):预写日志。数据写入MemStore前会先写入WAL,用于故障恢复。
ZooKeeper:负责集群协调,存储元数据表(
hbase:meta)的位置、监控RegionServer状态等。
4、HBase适用场景(与Hive对比)
为了更好理解HBase的定位,可以将其与Hive对比:
| 特性 | Hive | HBase |
|---|---|---|
| 定位 | 数据仓库,OLAP工具 | NoSQL数据库,大数据存储引擎 |
| 数据存储 | 不存储数据,映射HDFS文件 | 基于HDFS,但存储自身优化索引后的数据 |
| 数据管理 | 弱,依赖MapReduce,延迟高 | 强,基于列式存储,增删改高效,毫秒级响应 |
| 查询能力 | 强大的SQL查询与复杂统计 | 仅能通过RowKey查询(Get/Scan),不适合复杂统计 |
| 计算引擎 | MapReduce (默认,可换Tez/Spark) | 自身读写,可集成MapReduce/Spark进行计算 |
| 适用场景 | 离线分析、数据挖掘、允许延迟的OLAP | 实时读写、高并发OLTP、作为数据存储基石 |
结论:
HBase擅长实时读写和高并发OLTP场景,可作为大数据的存储基石。
Hive擅长复杂查询和离线分析(OLAP)。
两者特性互补,在实际项目中常集成使用:用HBase提供快速数据服务,用Hive进行复杂数据分析。
二、HBase安装
1、实验环境与前置软件
集群:三台CentOS 7服务器,主机名:hadoop01, hadoop02, hadoop03。
关键配置:配置时间同步;配置hadoop01到其他节点的SSH免密登录。
必须软件:JDK 8、Hadoop 3.2.2。
可选软件:MySQL (hadoop01)、Spark 3.1.1集群、Hive 3.1.2 (hadoop02,部署hiveserver2)。
2、安装Zookeeper
HBase依赖Zookeeper进行集群协调。建议独立搭建Zookeeper集群。
下载:zookeeper-3.5.8-bin.tar.gz。
解压:至
/app/zookeeper。配置(
conf/zoo.cfg):properties
dataDir=/app/zookeeper/data server.1=hadoop01:2888:3888 server.2=hadoop02:2888:3888 server.3=hadoop03:2888:3888
分发:将Zookeeper目录分发到三台服务器。
创建myid:在每台服务器的
dataDir目录下创建myid文件,内容分别为1,2,3。启动:在三台服务器上执行
bin/zkServer.sh start。使用jps看到QuorumPeerMain进程即成功。
3、安装HBase与搭建集群
下载:hbase-2.4.4-bin.tar.gz (需与Hadoop 3.2.2版本兼容)。
解压:至
/app/hbase。配置环境(
conf/hbase-env.sh):bash
export JAVA_HOME=/app/java/jdk1.8.0_212 export HBASE_MANAGES_ZK=false # 使用外部ZK
核心配置(
conf/hbase-site.xml):xml
<configuration> <property> <name>hbase.rootdir</name> <value>hdfs://hadoop01:8020/hbase</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.master.port</name> <value>16000</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value> </property> <property> <name>hbase.zookeeper.property.dataDir</name> <value>/app/zookeeper/data</value> </property> </configuration>
配置RegionServer节点(
conf/regionservers):text
hadoop01 hadoop02 hadoop03
链接Hadoop配置(保证配置一致):
bash
ln -s /app/hadoop/hadoop-3.2.2/etc/hadoop/core-site.xml /app/hbase/conf/ ln -s /app/hadoop/hadoop-3.2.2/etc/hadoop/hdfs-site.xml /app/hbase/conf/
分发HBase:将HBase目录分发到hadoop02和hadoop03。
配置环境变量(
~/.bash_profile):bash
export HBASE_HOME=/app/hbase export PATH=$PATH:$HBASE_HOME/bin
启动HBase集群:
bash
# 在 hadoop01 上启动 start-hbase.sh
使用
jps检查:hadoop01应有HMaster,三台都应有HRegionServer。访问Web UI:
http://hadoop01:16010。
注意事项:
必须配置时钟同步,否则会报
ClockOutOfSyncException。HBase内置Hadoop Jar包版本可能与实际不符,生产环境建议替换为集群一致版本。
三、HBase基础操作
1、基础Shell指令
bash
# 1. 进入HBase Shell hbase shell # 2. 帮助与查看 help list # 3. 创建表 (表名, 列簇名) create 'user', 'basicinfo' # 4. 插入/更新数据 (表名, RowKey, 列簇:列名, 值) put 'user', '1001', 'basicinfo:name', 'roy' put 'user', '1001', 'basicinfo:age', '18' # 5. 查询数据 get 'user', '1001' # 获取整行 get 'user', '1001', 'basicinfo:name' # 获取指定列 get 'user', '1001', {COLUMN => 'basicinfo:name', VERSIONS => 3} # 获取多版本 scan 'user' # 扫描全表 scan 'user', {STARTROW => '1001', STOPROW => '1003'} # 范围扫描(左开右闭) # 6. 查看表结构 desc 'user' # 7. 修改表结构(如修改列簇版本数) alter 'user', {NAME => 'basicinfo', VERSIONS => 5} # 8. 删除数据 delete 'user', '1002', 'basicinfo:sex' # 删除一列 deleteall 'user', '1003' # 删除整行 # 9. 清空与删除表 truncate 'user' disable 'user' drop 'user'2、HBase数据结构详解
RowKey:
唯一主键,最大长度64KB,按字典序字节数组存储。
访问方式仅三种:
get(单点)、scan(全表或范围)。设计至关重要:应包含重要查询字段,并利用排序特性将相关数据放一起。
列簇与列:
列属于列簇,列可动态扩展,数据以字节码存储。
同一列簇的列物理存储在一起,建议列簇内的列有相似结构和大小。
一个表建议1个列簇,最多不超过3个。
版本 (Version):
由
{row, column, version}唯一确定一个Cell。默认以时间戳为版本,降序存储,读取时返回最新版本。
可配置保留的版本数 (
VERSIONS)。
命名空间 (Namespace):
类似于数据库,用于逻辑隔离表。
默认有
hbase(系统表) 和default命名空间。
四、HBase原理
1、HBase写数据流程
Client向RegionServer发送写请求。
RegionServer将数据先写入WAL(预写日志),保证数据不丢失。
RegionServer将数据写入MemStore(内存)。
反馈Client写入成功。
MemStore刷写(Flush)到HFile的时机:
MemStore级别:单个MemStore大小达到阈值(默认128M)。
Region级别:Region内所有MemStore总和达到阈值。
RegionServer级别:全局MemStore达到低水位(触发刷写)或高水位(阻塞写入)。
WAL数量限制:WAL文件数量达到上限。
定期刷写:默认1小时(生产常关闭)。
手动刷写:
flush ‘table_name‘
2、HBase读数据流程
Client访问ZooKeeper,获取
hbase:meta表位置。从
hbase:meta表中根据RowKey找到目标Region所在的RegionServer。Client向目标RegionServer发起读请求。
RegionServer同时开启MemStoreScanner和StoreFileScanner,从内存和磁盘中读取数据。
合并结果,按时间戳返回最新版本的数据给Client。
读取过程中会使用BlockCache作为读缓存。
结论:由于写数据只需写内存+WAL,而读数据需要可能涉及磁盘IO,因此HBase的写性能通常优于读性能。
3、HBase底层存储与压缩
LSM树 (Log-Structured Merge-Tree):
HBase底层使用LSM树结构存储键值映射,将随机写转换为顺序写,极大提升写性能。
HBase 2.0+ 引入了内存压缩 (IN_MEMORY_COMPACTION),可选模式:
none,basic(默认),eager,adaptive,用于减少内存数据冗余和刷写频率。
文件压缩 (Compaction):
Minor Compaction:将相邻的小文件合并成大文件,不删除过期或标记删除的数据。性能消耗小。
bash
compact 'table_name'
Major Compaction:将Region下所有StoreFile合并成一个,会删除过期数据、标记删除的数据。性能消耗大,通常手动在业务低峰期触发。
bash
major_compact 'table_name'
删除数据的真相:
delete操作只是给数据打上标记。只有在Major Compaction时,标记删除的数据才会被物理删除。可通过scan ‘table‘, {RAW => true, VERSIONS => 10}查看包含删除标记的历史数据。
五、HBase客户端
1、REST API
HBase提供RESTful服务,默认端口8080(易冲突,可更改)。
bash
# 启动REST服务 (端口9090) bin/hbase-daemon.sh start rest -p 9090 # 停止 bin/hbase-daemon.sh stop rest
常用REST端点示例:
GET /status/cluster:查看集群状态。GET /namespaces:列出所有命名空间。GET /{namespace}/{table}/schema:查看表结构。
2、Java API
1. 添加Maven依赖
xml
<dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-client</artifactId> <version>2.4.4</version> </dependency> <dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-server</artifactId> <version>2.4.4</version> </dependency>
2. 核心Java代码示例
关键类:Connection,Admin,Table,Put,Get,Scan,Delete。
java
// 1. 获取配置和连接 Configuration config = HBaseConfiguration.create(); config.set("hbase.zookeeper.quorum", "hadoop01,hadoop02,hadoop03"); config.set("hbase.zookeeper.property.clientPort", "2181"); Connection connection = ConnectionFactory.createConnection(config); // 2. 获取Admin对象,进行DDL操作 Admin admin = connection.getAdmin(); // 3. 创建表(指定列簇) TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName)); ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(columnFamily)).build(); builder.setColumnFamily(cfd); admin.createTable(builder.build()); // 4. 获取Table对象,进行DML操作 Table table = connection.getTable(TableName.valueOf(tableName)); // 5. 插入数据 (Put) Put put = new Put(Bytes.toBytes(rowKey)); put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(column), Bytes.toBytes(value)); table.put(put); // 6. 查询数据 (Get) Get get = new Get(Bytes.toBytes(rowKey)); Result result = table.get(get); for (Cell cell : result.rawCells()) { System.out.println("RowKey:" + Bytes.toString(CellUtil.cloneRow(cell))); System.out.println("CF:" + Bytes.toString(CellUtil.cloneFamily(cell))); System.out.println("Qualifier:" + Bytes.toString(CellUtil.cloneQualifier(cell))); System.out.println("Value:" + Bytes.toString(CellUtil.cloneValue(cell))); } // 7. 扫描数据 (Scan) Scan scan = new Scan(); scan.withStartRow(Bytes.toBytes(startRow)); scan.withStopRow(Bytes.toBytes(stopRow), true); // 包含stopRow ResultScanner scanner = table.getScanner(scan); for (Result res : scanner) { /* 遍历处理 */ } // 8. 关闭资源 table.close(); admin.close(); connection.close();六、HBase优化
1、列簇设计优化
核心原则:一个表最好只有一个列簇,最多不要超过三个。
原因:
文件管理:HBase按列簇存储文件,列簇过多会导致小文件剧增,增加Compaction负担。
数据倾斜:Region按行切割,但列簇数据可能分布不均,导致热点Region。
性能:单列簇使HBase的文件管理更高效。
2、预分区与RowKey设计
预分区:在建表时预先创建多个Region,避免后期自动拆分导致的数据倾斜和热点问题。
预分区方法:
手动指定分割点:
bash
create 'staff', 'info', SPLITS => ['1000', '2000', '3000', '4000']
基于文件:将分割点写入文件
splits.txt,然后建表:bash
create 'staff', 'info', SPLITS_FILE => 'splits.txt'
十六进制序列(较少用):
bash
create 'staff3', 'info', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
RowKey设计原则:
散列性:避免热点。可将原始RowKey进行哈希(MD5、AES)或字符串反转。
有序性:利用字典序存储,将常一起查询的数据RowKey设计得相近。
长度适中:不宜过长,建议10-100字节。
常见技巧:加盐(前缀)、哈希、反转(如时间戳反转,将最新数据放前面)。
3、Hive与HBase集成
目标:利用HBase的快速读写能力存储数据,利用Hive的SQL能力进行分析查询。
集成步骤:
版本兼容:确保Hive与HBase版本兼容(Hive 3.1.2 默认集成 HBase ~2.0.0,与 HBase 2.4.4 经测试可兼容)。
配置HBase环境变量:在Hive所在节点的
~/.bash_profile中添加HBASE_HOME。配置Hive:在
hive-site.xml中添加HBase的ZooKeeper集群配置,使Hive能定位HBase Region。在Hive中创建映射表:
sql
CREATE TABLE hive_hbase_emp_table( empno int, ename string, job string, mgr int, hiredate string, sal double, comm double, deptno int ) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = " :key, -- 映射HBase的RowKey,对应Hive第一个字段empno info:ename, -- 列簇:列名 info:job, info:mgr, info:hiredate, info:sal, info:comm, info:deptno" ) TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table"); -- HBase中的表名执行此语句会在HBase中自动创建同名表。
通过Hive插入数据:
不能直接用
LOAD DATA。先准备一张Hive中间表
emp,并导入数据。通过
INSERT INTO hive_hbase_emp_table SELECT * FROM emp;将数据插入映射表,数据会同步写入HBase。
验证:
在Hive中执行复杂查询:
SELECT deptno, SUM(sal) FROM hive_hbase_emp_table GROUP BY deptno;在HBase Shell中查询数据:
scan 'hbase_emp_table'注意:HBase中的数据可能仍在MemStore,需执行
flush ‘hbase_emp_table‘才会刷写到HDFS。
集成本质:Hive通过MapReduce任务读取HBase中的数据(HBase深度集成了Hadoop,MapReduce可直接读取其HFile),从而提供SQL分析能力。
其他SQL-on-HBase方案:
Apache Phoenix:为HBase提供完整的JDBC支持和更优的SQL查询性能。
Spark on HBase:利用Spark读写HBase数据,进行复杂计算。
七、课程总结
HBase作为基于Hadoop的分布式NoSQL数据库,以其强悍的性能(支持千亿级读写、PB级存储、百万级并发)和稳定性,成为大数据存储的基石,在Facebook、阿里等公司深度使用。