一、基础概念
1. HBase 是什么?适用场景?
- 定义:分布式、面向列族的 NoSQL 数据库,基于 HDFS 存储,支持 PB 级数据的高吞吐随机读写。
- 场景:
- 海量时序数据(IoT 传感器日志)
- 用户行为日志(点击流、搜索记录)
- 实时查询引擎(用户画像)
- 稀疏宽表存储(动态列)
2. HBase 数据模型?
- 表(Table):由行和列组成。
- 行键(RowKey):唯一标识一行,按字典序排序。
- 列族(Column Family):列的逻辑分组,物理存储单位(如
cf1:name
,cf1:age
)。 - 单元格(Cell):由
(RowKey, Column Family:Qualifier, Timestamp)
唯一确定,存储值(Value)。 - 版本(Version):通过时间戳(Timestamp)实现多版本存储。
二、架构与组件
3. HBase 核心组件及作用?
- HMaster:
- 管理元数据(
hbase:meta
表) - 负责 Region 分配、负载均衡、DDL 操作(建表/删表)
- 管理元数据(
- RegionServer:
- 处理客户端读写请求
- 管理 Region(数据分片)
- 刷写 MemStore 到 HDFS(生成 HFile)
- ZooKeeper:
- 协调集群状态(选举 HMaster)
- 存储
hbase:meta
表位置
- HDFS:持久化存储数据(HFile)。
4. Region 是什么?如何分裂?
- Region:表按 RowKey 范围水平分片(如
[startKey, endKey]
)。 - 分裂触发条件:
- Region 大小超过阈值(默认 10GB)
- 手动触发
split
命令
- 分裂过程:
- RegionServer 创建两个子 Region。
- 父 Region 下线,子 Region 分配到其他 RegionServer。
- 父 Region 数据异步迁移到子 Region。
三、读写流程
5. 写数据流程(Put)
- 客户端从 ZooKeeper 获取
hbase:meta
表位置。 - 查询
hbase:meta
确定目标 Region 所在的 RegionServer。 - 数据写入 RegionServer 的 MemStore(内存) 和 WAL(Write-Ahead-Log)。
- MemStore 满后刷写到 HDFS 生成 HFile。
- WAL 用于故障恢复(RegionServer 宕机时重放日志)。
6. 读数据流程(Get)
- 客户端定位目标 Region(同写流程)。
- 按顺序查找:
- BlockCache(读缓存)
- MemStore(未刷写的内存数据)
- HFile(磁盘文件)
- 合并多版本数据,返回最新版本(或指定版本)。
四、关键机制
7. LSM 树(Log-Structured Merge-Tree)原理?
- 核心思想:将随机写转换为顺序写。
- 工作流程:
- 数据先写入内存(MemStore)。
- MemStore 满后刷写到磁盘生成有序的 HFile。
- 定期合并(Compaction)小文件为更大文件,删除过期数据。
8. Compaction 的作用与类型?
- 作用:
- 合并小文件,减少查询时的 I/O 次数。
- 清理过期数据(TTL)和标记删除的数据。
- 类型:
- Minor Compaction:合并相邻的小文件,不处理删除标记。
- Major Compaction:合并所有文件,清理删除数据(消耗资源大)。
9. WAL(Write-Ahead-Log)的作用?
- 核心作用:保证数据持久性。
- 数据写入 MemStore 前先写 WAL(HLog)。
- RegionServer 宕机后,通过重放 WAL 恢复未刷写的数据。
五、性能优化
10. RowKey 设计原则?
- 避免热点问题:
- 加盐(Salting):
hash(user_id) + user_id
- 反转时间戳:
Long.MAX_VALUE - timestamp
- 加盐(Salting):
- 保证有序性:按查询频率排序(如
user_id + timestamp
)。 - 长度控制:建议 10~100 字节(过长浪费存储,过短影响查询效率)。
11. 如何优化查询性能?
- 读优化:
- 开启 BlockCache(读缓存)。
- 使用 Bloom Filter 减少无效磁盘 I/O。
- 合理设计列族(避免过多列族)。
- 写优化:
- 批量写入(
Put List
)。 - 关闭 WAL(风险高,仅适用于可丢失数据场景)。
- 调整 MemStore 大小和刷写策略。
- 批量写入(
12. Bloom Filter 的作用?
- 原理:快速判断某个 RowKey 不存在于 HFile 中(避免无效磁盘扫描)。
- 使用场景:适用于随机点查(Get 操作)。
- 类型:
ROW
:检查 RowKey 是否存在。ROWCOL
:检查RowKey + Column
是否存在(更精确)。
六、故障处理与高可用
13. RegionServer 宕机如何处理?
- HMaster 通过 ZooKeeper 感知宕机。
- 将故障 RegionServer 的 Region 重新分配到其他节点。
- 重放 WAL 日志恢复未刷写的数据。
14. HBase 如何保证数据一致性?
- 行级原子性:单行数据的 Put/Delete 操作是原子的。
- 多版本控制:通过时间戳实现 MVCC。
- WAL 机制:确保写入不丢失。
七、生态集成
15. HBase 与 HDFS 的关系?
- 依赖关系:HBase 数据存储在 HDFS 上(HFile 是 HDFS 文件)。
- 分工:
- HDFS 提供高可靠存储(副本机制)。
- HBase 提供低延迟随机读写能力。
16. 如何与 Spark 集成?
- 使用 Spark SQL 或 DataFrame API:
复制
val hbaseDF = spark.read.format("org.apache.hadoop.hbase.spark") .option("hbase.table", "user_table") .option("hbase.columns.mapping", "name STRING :cf.name, age INT :cf.age") .load()
- 使用 HBaseContext(官方库):
val hbaseContext = new HBaseContext(spark.sparkContext, config) hbaseContext.bulkPut(rdd, tableName, putConverter)
八、高频进阶题
17. HBase 与 RDBMS 的区别?
特性 | HBase | RDBMS |
---|---|---|
数据模型 | 列式存储,稀疏表 | 行式存储,固定 Schema |
扩展性 | 水平扩展(RegionServer) | 垂直扩展(硬件升级) |
事务支持 | 仅单行事务 | 多行事务(ACID) |
查询语言 | 无 SQL,API/Scan 操作 | SQL |
适用场景 | 海量数据高吞吐读写 | 复杂查询与事务处理 |
18. HBase 如何实现范围查询?
- Scan 操作:
- 设置
startRow
和stopRow
。 - 利用 RowKey 有序性,顺序扫描 Region。
- 设置
- 优化:
- 使用 Filter(如
PrefixFilter
,PageFilter
)。 - 避免全表扫描(合理设计 RowKey)。
- 使用 Filter(如
19. HBase 的 Coprocessor 是什么?
- 作用:在 RegionServer 上执行自定义逻辑(类似数据库存储过程)。
- 类型:
- Observer:拦截数据操作(如
prePut
,postDelete
)。 - Endpoint:在 Region 上执行分布式计算(如聚合统计)。
- Observer:拦截数据操作(如
九、实战场景题
20. 设计一个实时用户行为分析系统
- 存储选型:HBase + Kafka + Spark Streaming。
- HBase 表设计:
- RowKey:
hash(user_id) + user_id + timestamp
- 列族:
cf:action
(行为类型)cf:detail
(行为详情)
- RowKey:
- 写入:Kafka 消费数据后批量写入 HBase。
- 查询:按
user_id
前缀快速扫描行为记录。
附:面试技巧
- 强调设计经验:结合项目说明 RowKey 设计、Compaction 调优等。
- 对比其他数据库:解释为何选 HBase 而非 Cassandra/MongoDB。
- 故障处理思路:从 WAL、Region 分配、HDFS 副本多角度分析。