大厂Hbase八股文面试题及参考答案(百度米哈游完美世界多家面经汇总)
介绍下 HBase?HBase 优缺点有哪些?
HBase 是一个分布式、面向列的 NoSQL 数据库,基于 Hadoop 的 HDFS 存储系统设计,适合处理海量数据的实时读写需求。它模仿 Google 的 Bigtable 模型,通过强一致性和水平扩展能力支持高并发场景。
核心特点:
- 列式存储:数据按列族(Column Family)组织,适合稀疏数据场景。
- 强一致性:基于 HDFS 的多副本机制,保证数据可靠性。
- 自动分片:数据按 Region 自动分片,支持动态扩展。
- 版本控制:每个单元格(Cell)支持多版本数据存储。
优点:
- 高扩展性:通过增加 RegionServer 节点轻松扩展集群容量。
- 高吞吐与低延迟:LSM 树结构优化写入,BlockCache 提升读取性能。
- 灵活数据模型:无需预定义表结构,支持动态列和稀疏数据。
- 与 Hadoop 生态无缝集成:可直接使用 MapReduce 或 Spark 进行数据分析。
缺点:
- 不支持复杂查询:缺乏 SQL 支持,需通过 Scan 或 Filter 实现简单查询。
- 单点故障风险:HMaster 负责元数据管理,若未配置高可用可能成为瓶颈。
- 内存消耗高:MemStore 和 BlockCache 依赖内存,需合理配置资源。
- 无事务支持:仅支持行级原子性,跨行操作需自行处理一致性。
说下 HBase 原理?介绍下 HBase 架构?
HBase 的核心原理基于 LSM 树(Log-Structured Merge Tree),通过将随机写入转换为顺序写入提升性能。数据首先写入内存(MemStore),达到阈值后刷写到磁盘(HFile),后台定期合并小文件以减少读取开销。
架构组成:
- HMaster:负责元数据管理(如表结构、Region 分配)。处理 Region 的负载均衡与故障转移。注意:生产环境需配置多个 HMaster 以避免单点故障。
- RegionServer:管理多个 Region,处理客户端读写请求。包含 **MemStore(写缓存)**和 BlockCache(读缓存)。
- ZooKeeper:协调集群状态,监控 RegionServer 存活。存储 HBase 的元数据(如 HMaster 地址)。
- HDFS:持久化存储 HFile 和预写日志(WAL)。
数据组织:
- 表按行键(Row Key)水平划分为多个 Region,每个 Region 包含连续的行区间。
- 列族(Column Family)是物理存储单元,不同列族的数据独立存储。
HBase 读写数据流程是怎样的?HBase 的读写缓存是怎样的?在删除 HBase 中的一个数据的时候,它什么时候真正进行删除?
写入流程:
- 客户端通过 ZooKeeper 定位目标 Region 所在的 RegionServer。
- 数据先写入 WAL(Write-Ahead Log),确保故障恢复能力。
- 写入 MemStore,内存达到阈值后异步刷写到 HDFS 生成 HFile。
读取流程:
- 客户端从 ZooKeeper 和 Meta 表获取 Region 位置。
- 按 BlockCache → MemStore → HFile 的顺序查找数据,合并结果返回。
读写缓存机制:
- BlockCache:缓存频繁访问的 HFile 数据块(如 Bloom Filter),采用 LRU 策略淘汰。
- MemStore:写缓存,按列族隔离,刷写后生成新的 HFile。
数据删除逻辑:
- 删除操作会插入一个 墓碑标记(Tombstone),而非立即物理删除数据。
- 墓碑标记在以下两种场景生效: Minor Compaction:合并 HFile 时跳过标记的数据。Major Compaction:彻底清理标记数据并释放空间。
HBase 中的二级索引是怎样的?
HBase 原生不支持二级索引,但可通过以下方案实现类似功能:
1. 协处理器(Coprocessor):
- Observer:在数据写入时同步更新索引表。
- Endpoint:自定义聚合逻辑,但需维护索引一致性。
- 优点:实时性强,索引与数据同步更新。
- 缺点:增加写入延迟,索引表可能成为瓶颈。
2. 外部索引表:
- 手动创建独立表存储索引数据(如行键与索引列的映射)。
- 优点:灵活性高,支持复杂查询。
- 缺点:需应用层维护一致性,双写可能引入数据不一致。
3. Phoenix:
- 基于 HBase 的 SQL 层,内置全局二级索引(Global Index)和本地索引(Local Index)。
- 全局索引:独立表存储索引,适合读多写少场景。
- 本地索引:与数据表共址,写性能更优。
4. Elasticsearch 集成:
- 通过工具(如 Lily)将 HBase 数据同步到 Elasticsearch,利用其全文检索能力。
HBase 的 RegionServer 宕机以后怎么恢复?
恢复流程:
- 故障检测:ZooKeeper 通过心跳机制检测 RegionServer 宕机,通知 HMaster。
- Region 重新分配:HMaster 将宕机节点上的 Region 标记为未分配,并重新分配到其他活跃 RegionServer。
- WAL 回放:从 HDFS 读取宕机节点的 WAL 日志,按时间顺序重放未持久化的操作(MemStore 中的数据)。回放完成后,新 RegionServer 对外提供服务。
关键机制:
- WAL 持久化:所有写入操作先记录到 HDFS,确保故障后数据不丢失。
- Region 副本(可选):HBase 2.0+ 支持 Region 多副本,缩短故障恢复时间。
影响与优化:
- 恢复时间:取决于 WAL 日志大小和网络带宽。
- 预写日志分割:HMaster 将 WAL 按 Region 切分,并行回放以加速恢复。
- 避免数据倾斜:合理设计行键,防止单个 RegionServer 负载过重。
HBase 的一个 region 由哪些东西组成?
在 HBase 中,Region 是数据存储和管理的核心单元,每个 Region 对应表中连续的一段行键范围(例如从 row1
到 row100
)。其组成结构如下:
- Store:每个 Region 按列族(Column Family)划分为多个 Store。例如,若表有 info 和 data 两个列族,则 Region 会包含两个 Store。Store 是物理存储的最小单位,负责管理内存和磁盘数据。
- MemStore:每个 Store 对应一个 MemStore(写缓存),用于暂存写入数据。数据写入时先进入 MemStore,排序后刷写到磁盘形成 HFile。
- HFile:存储在 HDFS 上的数据文件,采用 LSM 树结构,包含多级索引(如 Bloom Filter 和 Block Index)以加速查询。每个 Store 可能有多个 HFile,后台通过合并(Compaction)优化文件数量和大小。
- WAL(预写日志):虽然 WAL 由 RegionServer 全局管理,但每个 Region 的写入操作会记录到 WAL,用于故障恢复。
- Region 元数据:包括行键范围、所属表、列族配置等信息,存储在 HBase 的 Meta 表中。
核心作用:
- 水平扩展:Region 分裂(Split)机制允许数据分布到多台机器。
- 读写隔离:MemStore 处理写入,HFile 处理读取,通过合并平衡性能。
HBase 高可用怎么实现?
HBase 的高可用性通过以下机制保障:
1. HMaster 高可用:
- 部署多个 HMaster 节点,通过 ZooKeeper 选举机制确保主备切换。
- 主 HMaster 负责元数据管理,备节点监听状态并在主节点宕机时接管。
2. RegionServer 容错:
- ZooKeeper 心跳检测:实时监控 RegionServer 存活状态,宕机时触发 HMaster 重新分配 Region。
- WAL 回放:RegionServer 故障后,HMaster 从 HDFS 读取其 WAL 日志,在其他节点重放未持久化的数据。
3. 数据持久化:
- HDFS 多副本:默认 3 副本存储 HFile 和 WAL,防止数据丢失。
- WAL 同步写入:数据先写入 WAL 再进入 MemStore,确保故障时可恢复。
4. Region 副本(HBase 2.0+):
- 支持为单个 Region 配置多个副本,分布在不同 RegionServer 上。
- 主副本处理读写,备副本同步数据,主副本宕机时备副本快速接管。
优化建议:
- 避免单点瓶颈:配置至少 3 个 ZooKeeper 节点和 2 个 HMaster。
- 合理设置超时参数:如
zookeeper.session.timeout
控制故障检测灵敏度。
为什么 HBase 适合写多读少业务?列式数据库的适用场景和优势是什么?列式存储的特点有哪些?
HBase 写多读少的优势:
- LSM 树优化写入:数据先写入内存(MemStore),批量刷盘减少磁盘随机 I/O。
- 异步合并:后台 Compaction 将小文件合并为大文件,降低读取时的寻址开销。
- 高吞吐:顺序写入 HDFS 和 WAL,适合日志、时序数据等写入密集型场景。
列式数据库的适用场景:
- OLAP 分析:需扫描大量行但少量列的聚合查询(如 SUM、AVG)。
- 稀疏数据:列独立存储,适合字段稀疏或动态增减的场景。
- 高压缩率:同列数据类型一致,压缩效率更高(如 Run-Length 编码)。
列式存储的核心特点:
按列存储 | 每列数据连续存储,减少读取无关列的数据量。 |
高效压缩 | 同列数据重复率高,压缩比显著优于行式存储。 |
延迟物化 | 仅读取查询涉及的列,减少 I/O 和内存占用。 |
向量化处理 | 批量处理同列数据,充分利用 CPU 缓存和 SIMD 指令。 |
对比行式存储:
- 写入性能:行式存储更适合频繁插入整行数据的场景(如 OLTP)。
- 读取性能:列式存储在分析型查询中表现更优。
HBase 的 rowkey 设计原则是什么?HBase 的 rowkey 为什么不能超过一定长度?为什么要唯一?rowkey 太长会影响 Hfile 的存储吗?HBase 的 RowKey 设置讲究的原因是什么?
RowKey 设计原则:
- 唯一性:RowKey 是数据的唯一标识,重复会导致数据覆盖。
- 长度控制:建议 10~100 字节,过长会降低 MemStore 和 HFile 索引效率。
- 散列分布:避免连续值(如时间戳)导致热点问题,可采用加盐哈希(如
MD5(username)[0:4] + username
)。 - 查询友好:将常用查询条件前置(如
userid_actiontime
)。
RowKey 长度限制的影响:
- 内存开销:每个 RowKey 会存储在 MemStore 和 BlockCache 中,过长会挤占内存空间。
- HFile 索引膨胀:HFile 的 Bloom Filter 和 Block Index 需记录 RowKey 前缀,长度增加会降低索引效率。
- 网络传输:RegionServer 需在 RPC 中传递 RowKey,过大会增加序列化开销。
RowKey 必须唯一的原因:
- HBase 中相同 RowKey 的多次写入会视为更新操作,旧版本数据可能被覆盖(取决于版本数配置)。
设计 RowKey 的深层考量:
- 负载均衡:良好的 RowKey 设计可避免 RegionServer 热点,例如将随机前缀(如
hash(userid) % 100
)加入 RowKey。 - 查询性能:RowKey 是唯一全局有序索引,设计需匹配业务查询模式(如范围扫描或精确查询)。
HBase 的大合并、小合并是什么?大合并是如何做的?为什么要大合并?
小合并(Minor Compaction):
- 触发条件:单个 Store 的 HFile 数量达到阈值(如
hbase.hstore.compactionThreshold=3
)。 - 操作过程:将相邻的多个小 HFile 合并为一个更大的 HFile,减少读取时的文件寻址次数。
- 特点:仅合并文件,不处理删除标记或过期数据,I/O 开销较低。
大合并(Major Compaction):
- 触发条件:周期性触发(默认 7 天)或手动执行。
- 操作过程: 将一个 Store 的所有 HFile 合并为一个新 HFile。清理墓碑标记(Tombstone) 和过期版本数据,释放磁盘空间。更新 HFile 的元数据和索引。
- 特点:I/O 和计算密集型操作,可能影响集群性能,需避开业务高峰期。
大合并的必要性:
- 空间回收:物理删除标记数据,避免存储浪费。
- 查询优化:减少读取时需要扫描的文件数量,提升性能。
- 数据一致性:确保多版本数据和删除操作最终生效。
优化建议:
- 自动合并策略:根据业务负载调整合并周期和触发条件。
- 分时调度:在低峰期触发 Major Compaction。
- 关闭自动 Major Compaction:在写入密集场景中手动控制合并时机。
HBase 和关系型数据库(传统数据库)的区别(优点)有哪些?
HBase 与传统关系型数据库(如 MySQL、Oracle)在设计目标和适用场景上存在显著差异,核心区别如下:
1. 数据模型差异:
- HBase:基于列族存储,数据按行键(RowKey)和列族组织,支持动态列和稀疏数据。
- 关系型数据库:基于行存储,数据按预定义的表结构和固定列存储,适合结构化数据。
2. 扩展性与性能:
- HBase: 水平扩展:通过增加 RegionServer 节点轻松扩展至 PB 级数据。高写入吞吐:LSM 树结构优化写入,适合日志、时序数据等写多读少场景。
- 关系型数据库: 垂直扩展:通常通过升级硬件(如 CPU、内存)提升性能,扩展成本高。强事务支持:支持 ACID 事务,适合需要复杂事务的业务(如银行系统)。
3. 查询能力:
- HBase: 仅支持单行事务和基于 RowKey 的范围扫描(Scan)。无原生 SQL 支持,需通过 API 或 Phoenix 等工具实现类 SQL 查询。
- 关系型数据库: 支持复杂查询(如 JOIN、子查询)、聚合函数和二级索引。提供标准 SQL 接口,开发门槛低。
4. 一致性模型:
- HBase:强一致性(基于 HDFS 多副本和 WAL)。
- 关系型数据库:强一致性(通过锁和事务机制)。
5. 适用场景对比:
数据规模 | 海量数据(TB/PB 级) | 中小规模(GB/TB 级) |
读写模式 | 写多读少,高吞吐写入 | 读写均衡,低延迟事务 |
灵活性 | 动态列,无需预定义模式 | 固定表结构,需预先设计 |
HBase 数据结构是怎样的?为什么 HBase 随机查询很快?
HBase 数据结构:
- 逻辑视图:数据按行键(RowKey) 全局有序排列,每行包含多个列族(Column Family)。列族下包含多个列限定符(Qualifier),每个单元格(Cell)可存储多个版本的数据。
- 物理存储:数据按 Region 分片存储,每个 Region 包含多个 Store(对应一个列族)。Store 由 MemStore(内存) 和 HFile(磁盘) 组成,写入数据先进入 MemStore,刷盘后生成 HFile。
随机查询快的原因:
- RowKey 有序性:数据按 RowKey 排序存储,通过 Region 分区和 HFile 索引快速定位目标数据块。
- 多级缓存机制:BlockCache:缓存频繁访问的 HFile 数据块(如 Bloom Filter),减少磁盘 I/O。MemStore:最新写入数据可直接从内存读取,无需访问磁盘。
- Bloom Filter:快速判断某 RowKey 是否存在于 HFile 中,避免无效的磁盘扫描。
- LSM 树优化:通过 Compaction 合并小文件,减少读取时需要访问的 HFile 数量。
HBase 的 LSM 结构是怎样的?HBase 的 Get 和 Scan 的区别和联系是什么?
LSM 结构解析:
- 写入流程:数据先写入 MemStore(内存),同时记录到 WAL(预写日志)。MemStore 达到阈值后,数据刷写到 HDFS 生成 HFile(有序键值存储)。后台 Compaction 合并 HFile,减少文件数量并清理过期数据。
- 读取流程:依次检查 BlockCache → MemStore → HFile,合并结果返回客户端。
Get 与 Scan 的对比:
查询类型 | 单行精确查询 | 多行范围扫描 |
性能 | 毫秒级延迟(利用索引和缓存) | 依赖扫描范围,可能涉及多个 Region |
使用场景 | 基于 RowKey 的实时查询 | 数据分析、全表扫描 |
资源消耗 | 低(单行数据) | 高(大量 I/O 和网络传输) |
联系:
- 两者均基于 RowKey 的有序性实现高效查询。
- Scan 可视为多次 Get 的批量操作,但需注意设置合理的
caching
和batch
参数以减少开销。
HBase 数据的存储结构(底层存储结构)是怎样的?HBase 数据 compact 流程是怎样的?
底层存储结构:
- HFile:实际存储在 HDFS 上的文件,结构如下: Data Block:存储键值对,默认大小 64KB。Meta Block:存储 Bloom Filter 等元数据。Trailer:记录索引和元数据的偏移量。采用 KeyValue 格式,每个条目包含 RowKey、列族、列限定符、时间戳和值。
- WAL(预写日志):记录所有写入操作,用于故障恢复,存储在 HDFS 上。
Compaction 流程:
- 触发条件:Minor Compaction:合并相邻的多个小 HFile 为大文件。Major Compaction:合并所有 HFile 并清理删除数据。
- 执行步骤:从 HDFS 读取待合并的 HFile,按 RowKey 排序后合并为新文件。更新元数据,删除旧文件。
- 核心作用:减少文件数量,提升读取效率。清理过期版本和墓碑标记,释放存储空间。
HBase 的预分区是怎样的?HBase 的热点问题有哪些?
预分区(Pre-splitting):
- 目的:避免自动分区导致的数据倾斜(如所有数据集中在单个 Region)。
- 实现方式: 建表时指定 Split Keys(如 create 'table', 'cf', {SPLITS => ['a', 'b', 'c']})。根据业务数据分布选择合适的分区策略(如哈希、范围划分)。
热点问题:
- 成因:RowKey 设计不当:例如使用连续时间戳作为前缀,导致写入集中在单个 Region。访问模式倾斜:高频访问同一 RowKey 或小范围数据。
- 解决方案:加盐(Salting):在 RowKey 前添加随机前缀(如 hash(userid) % 100)。哈希化:对自然键(如用户 ID)进行哈希,确保均匀分布。反转时间戳:将时间戳高位反转(如 Long.MAX_VALUE - timestamp),避免新数据集中写入。范围分区:根据业务查询模式设计 RowKey,分散负载。
优化效果:
- 通过预分区和 RowKey 设计,可将数据均匀分布到多个 RegionServer,提升集群吞吐量。
HBase 的 memstore 冲刷条件是什么?HBase 的 MVCC 是怎样的?
MemStore 冲刷条件:
MemStore 是 HBase 的写缓存,数据写入时先暂存于此,当满足以下条件时会触发刷写(Flush)到磁盘生成 HFile:
- 内存阈值触发:单个 MemStore 大小达到
hbase.hregion.memstore.flush.size
(默认 128MB)。 - 全局内存限制:RegionServer 所有 MemStore 总大小超过
hbase.regionserver.global.memstore.size
(默认堆内存的 40%),此时按 Region 的写入顺序强制刷写。 - WAL 文件数量限制:当 WAL 文件数量超过
hbase.regionserver.max.logs
(默认 32),触发刷写以减少日志数量。 - 手动触发:通过 API 或 HBase Shell 执行
flush
命令主动刷写。
冲刷流程:
- 刷写前会先冻结当前 MemStore,生成新的 MemStore 继续接收写入。
- 数据按 RowKey 排序后写入 HDFS 生成 HFile,并记录元数据到 HFile 的 Trailer 部分。
MVCC(多版本并发控制):
- 写入场景:每次写入操作会分配一个递增的版本号(Timestamp),数据以多版本形式存储。
- 读取场景:读取时根据版本号选择最新可见版本,避免脏读和写阻塞。
- 实现机制: 写操作:新数据直接追加到 MemStore,旧版本标记为过期但不会立即删除。读操作:扫描 MemStore 和 HFile,过滤掉被后续操作覆盖的旧版本数据。
- 优势: 读写并发时无需加锁,提升吞吐量。通过 Compaction 清理过期版本,保证存储效率。
既然 HBase 底层数据是存储在 HDFS 上,为什么不直接使用 HDFS,而还要用 HBase?
HDFS 和 HBase 的定位不同,前者是分布式文件系统,后者是分布式数据库,两者的核心差异如下:
HDFS 的局限性:
- 仅支持批量读写:HDFS 适合顺序访问大文件,无法高效处理随机读写。
- 无结构化数据管理:缺少数据索引、版本控制、事务等数据库特性。
- 高延迟:读取数据需遍历整个文件,不适合实时查询。
HBase 的核心价值:
- 随机读写优化:通过 MemStore 和 LSM 树将随机写转换为顺序写,利用 BlockCache 加速读。
- 结构化数据模型:支持行键、列族、多版本等特性,提供灵活的数据组织方式。
- 高可用与自动扩展:Region 自动分裂和故障转移机制,无需人工干预数据分布。
- 实时查询能力:基于 RowKey 的 Get 和 Scan 操作可实现毫秒级响应。
类比场景:
- HDFS 类似“仓库”,适合存储原始日志或备份文件。
- HBase 类似“货架”,提供分类、索引和快速存取能力。
HBase 和 Phoenix 的区别是什么?HBase 支持 SQL 操作吗?
HBase 的 SQL 支持:
- 原生不支持 SQL:HBase 仅提供 Put、Get、Scan 等 API,需通过代码或工具实现复杂查询。
- Phoenix 的角色: 作为 HBase 的SQL 中间件,提供 JDBC 接口和类 SQL 语法(如 SELECT、JOIN)。将 SQL 查询转换为 HBase 的 Scan 和 Filter 操作,并优化执行计划。
核心区别:
查询语言 | API 接口(Java/Python) | ANSI SQL |
二级索引 | 需手动实现 | 内置全局和本地索引 |
事务支持 | 仅行级原子性 | 跨行事务(实验性) |
性能优化 | 依赖 RowKey 设计 | 自动优化查询计划 |
Phoenix 的适用场景:
- 需要复杂查询(如聚合、JOIN)的业务。
- 希望降低开发门槛,复用现有 SQL 生态。
HBase 适合读多写少还是写多读少?HBase 表设计要注意什么?Region 分配是怎样的?HBase 的 Region 切分是怎样的?
读写场景适配性:
- 写多读少:LSM 树结构优化写入吞吐,适合日志、时序数据等场景。
- 读多场景:需通过 BlockCache、布隆过滤器和 RowKey 设计提升性能。
表设计要点:
- RowKey 设计: 避免热点:散列或加盐处理(如 hash(userid) + timestamp)。查询友好:将常用查询条件前置(如 region_userid)。
- 列族数量:通常不超过 3 个,过多列族会降低 Compaction 效率。
- 数据版本:根据业务需求设置
VERSIONS
,避免存储冗余数据。
Region 分配与切分:
- 初始分配:建表时通过预分区(Pre-splitting)手动指定 Split Keys。
- 自动切分:当 Region 大小达到
hbase.hregion.max.filesize
(默认 10GB)时,按中间 RowKey 分裂为两个子 Region。 - 负载均衡:HMaster 监控 Region 分布,将密集节点的 Region 迁移至空闲节点。
切分影响:
- 优点:分散数据压力,提升并行处理能力。
- 缺点:分裂期间 Region 短暂不可用,可能引发性能波动。
如何查询散列后的 rowkey?
散列 RowKey 的常见场景是为解决热点问题,例如对原始 RowKey 进行 MD5 或取模运算。查询时需按相同规则处理才能准确定位数据。
查询方法:
- 精确查询:对查询条件应用相同的散列算法,生成散列后的 RowKey。例如:查询 userid=123,需先计算 hash(123),再执行 Get 操作。
- 范围查询:散列后的 RowKey 失去原始顺序,无法直接范围扫描。替代方案: 在应用层存储原始 RowKey 与散列值的映射关系,查询时转换为多个散列区间。使用 Phoenix 的全局索引或本地索引,通过 SQL 条件自动处理散列逻辑。
设计权衡:
- 写入均匀性:散列能分散负载,但增加了查询复杂度。
- 业务适配:需根据查询模式选择散列算法(如一致性哈希可减少迁移开销)。
示例代码(非实际代码,仅逻辑描述):
# 写入时生成散列 RowKey hashed_key = md5(original_key).hexdigest() hbase.put(hashed_key, data) # 查询时重新计算散列值 target_hash = md5(query_key).hexdigest() result = hbase.get(target_hash)
HBase/mysql 的主从复制机制是什么?
HBase 和 MySQL 的主从复制机制设计目标不同,分别服务于分布式数据库和传统关系型数据库的需求,其实现方式和应用场景存在显著差异:
HBase 主从复制:
- 核心机制:基于 WAL(Write-Ahead Log) 的异步复制,将主集群(Master)的写入操作同步到从集群(Slave)。
- 触发条件: 主集群的 RegionServer 将写入操作记录到 WAL。异步线程读取 WAL 并发送到从集群的 RegionServer。
- 数据流向: 主集群 → ZooKeeper 协调 → 从集群。支持跨数据中心复制(如灾备场景)。
- 一致性级别:最终一致性,从集群数据可能存在延迟。
- 配置方式:通过
peer
配置指定从集群地址和复制规则。
MySQL 主从复制:
- 核心机制:基于 binlog(二进制日志) 的异步或半同步复制,主库(Master)将数据变更同步到从库(Slave)。
- 触发条件: 主库将事务写入 binlog。从库的 I/O 线程拉取 binlog 并写入中继日志(Relay Log)。从库的 SQL 线程重放中继日志。
- 数据流向:主库 → 从库(单向)。
- 一致性级别: 异步复制:数据延迟较高,主库宕机可能导致数据丢失。半同步复制:主库提交事务前需至少一个从库确认,降低丢失风险。
对比总结:
数据粒度 | 行级或列族级 | 事务级(行或语句) |
拓扑结构 | 多主或多从(需手动配置) | 一主多从 |
适用场景 | 跨数据中心容灾、数据分发 | 读写分离、负载均衡 |
故障恢复 | 依赖 WAL 重放 | 依赖 binlog 和中继日志 |
HBase 的三级索引是什么?
HBase 原生仅支持基于 RowKey 的一级索引(即主索引),但通过外部工具或自定义方案可实现二级索引和三级索引。这里的“三级索引”通常指以下两种含义:
1. 多层索引结构:
- 一级索引:RowKey 索引,全局有序,直接定位数据。
- 二级索引:基于列值构建的辅助索引(如通过协处理器实现)。
- 三级索引:在二级索引基础上进一步聚合或分层,例如: 按时间范围划分的索引(如 日期_用户ID)。联合多列的复合索引(如 品牌_价格_销量)。
2. 基于外部组件的索引:
- Phoenix 全局索引:独立表存储索引数据,支持快速查询。
- Elasticsearch 集成:将 HBase 数据同步到 ES,利用其倒排索引实现全文检索。
- HBase+Solr:通过 Lily Indexer 同步数据到 Solr 构建多维索引。
三级索引的典型实现:
- 适用场景:需要同时按多个非 RowKey 字段查询(如
查询某地区价格低于 100 的商品
)。 - 挑战: 数据一致性:需保证索引与主数据同步更新。写入性能:多级索引增加写入延迟和资源消耗。
在定位到 region 的 table 获取数据时,需要打开和读取所有的 hfile 吗?
不需要。HBase 通过以下机制避免全量扫描 HFile,从而提升读取效率:
- Bloom Filter:快速判断目标 RowKey 是否存在于某个 HFile 中,跳过无关文件。存储在 HFile 的 Meta Block 中,内存加载后直接使用。
- Block Cache:缓存频繁访问的 HFile 数据块(如最近读取的 Data Block)。优先从内存读取,减少磁盘 I/O。
- HFile 索引结构:多级索引:包括文件级索引(Trailer 中的 Data Index)和 Block 内的行键索引。通过二分查找或跳跃表定位目标 Data Block。
- Compaction 优化:定期合并小文件,减少需要扫描的 HFile 数量。Major Compaction 后,单个列族通常仅保留一个 HFile。
读取流程精简版:
- 从 BlockCache 和 MemStore 查找最新数据。
- 对 HFile 按时间戳倒序扫描,找到第一个匹配的单元格后终止(版本控制)。
在 HBase 读写流程中,Hlog 的作用是什么?
HLog(预写日志) 是 HBase 实现数据持久化和故障恢复的核心组件,其作用贯穿整个读写生命周期:
写入流程中的 HLog:
- 写入顺序:数据先写入 HLog,再写入 MemStore。
- 持久化保证:即使 RegionServer 宕机,未刷盘的数据仍可通过 HLog 恢复。
- 日志结构:按时间顺序记录所有 Put、Delete 等操作,存储在 HDFS 上。
故障恢复流程:
- 检测宕机:ZooKeeper 发现 RegionServer 失联,通知 HMaster。
- 重放 HLog: HMaster 从 HDFS 读取宕机节点的 HLog。按 Region 拆分日志,分发到新分配的 RegionServer 回放。
- 数据一致性:回放完成后,MemStore 数据与故障前一致。
HLog 的管理:
- 滚动更新:当 HLog 文件大小超过阈值(默认 128MB)或时间到期(默认 1 小时),创建新文件。
- 失效清理:MemStore 刷盘后,对应的 HLog 可被安全删除。
性能影响:
- 优势:保障数据可靠性,避免写入丢失。
- 代价:追加写入 HLog 增加少量延迟(可通过异步写入优化)。
17年+码农经历了很多次面试,多次作为面试官面试别人,多次大数据面试和面试别人,深知哪些面试题是会被经常问到。 在多家企业从0到1开发过离线数仓实时数仓等多个大型项目,详细介绍项目架构等企业内部秘不外传的资料,介绍踩过的坑和开发干货,分享多个拿来即用的大数据ETL工具,让小白用户快速入门并精通,指导如何入职后快速上手。 计划更新内容100篇以上,包括一些企业内部秘不外宣的干货,欢迎订阅!