05-04-B-HBase与时序库面试与生产事故实战

05-04-B-HBase与时序库面试与生产事故实战

️ 关键词:HBase 面试题 · LSM-Tree · RowKey 设计 · 写热点 · Region · 时序库 · 降采样 · 监控存储

📌 导读 :A 篇讲"LSM-Tree 怎么工作、RowKey 怎么设计、时序库怎么降采样",本篇讲"面试官怎么考、生产上怎么炸、炸了怎么救 "。高频题按知识依赖链一问一答连贯展开 (每题: 30 秒电梯版 → 深挖版 → 追问链),事故按场景 → 根因 → 预防 → 解决 → 一句话教训五段式复盘。原理细节标注"见 A 篇 x.x 节"。


📑 目录


一、高频面试题精讲(连贯问答链)

链条①:LSM-Tree 与存储四连问

Q1:HBase 为什么写入快?LSM-Tree 的原理?

** 30 秒电梯版**

LSM-Tree 写流程(见 A 篇 2.1):

  1. 写 WAL(HLog):预写日志,持久化保证,crash 时恢复未刷盘数据;
  2. 写 MemStore :内存有序写缓冲,按 RowKey 排序------写入毫秒级,无磁盘 IO;
  3. MemStore 满刷盘:默认 128MB 满后 Flush 成 HFile(有序数据文件,不可变);
  4. 后台 Compaction:合并多个 HFile 成大 HFile,清理删除标记。

为什么快 :写路径全程顺序 IO(MemStore 内存写 + HFile 顺序刷盘),没有 B+ 树的随机写维护开销。

一句话总结 :LSM-Tree 把随机写变成顺序写------写 WAL 保命、写 MemStore 求快、刷盘成 HFile、后台 Compaction 合并。

** 深挖版**

要点 说明
WAL 的作用 MemStore 是内存,crash 会丢------WAL 先落盘,恢复时重放 WAL
HFile 不可变 和 ES Segment 同款思想------不可变 = 无锁 + 可压缩 + 可缓存
与 ClickHouse MergeTree 对比 同源 LSM 思想:part/HFile 顺序写 + 后台 merge/Compaction------ClickHouse 为列存分析优化,HBase 为 KV 点查优化

** 追问链**:读取流程呢?→ Q2


Q2:HBase 读取为什么比写入慢?怎么优化?

** 30 秒电梯版**

读流程 (见 A 篇 2.2):查 MemStore → BlockCache(读缓存)→ 多个 HFile(从新到旧,布隆过滤器排除不含目标 RowKey 的 HFile)→ 合并多版本。

读慢的原因(读放大) :一行数据可能分散在 MemStore + 多个 HFile 中------要查多层、合并多版本。

优化手段:

  1. Compaction:减少 HFile 数量 = 减少读放大;
  2. 布隆过滤器 :快速排除不含目标的 HFile------点查加速神器;
  3. BlockCache :热数据缓存内存------热点查询加速。

一句话总结 :读放大是 LSM-Tree 的代价------Compaction 减 HFile 数、布隆过滤器跳过无关文件、BlockCache 缓存热数据,三板斧缓解读放大。

** 深挖版**

要点 说明
布隆过滤器原理 概率数据结构------判断"一定不在"或"可能在",假阳性率可配(默认 1%)
Major vs Minor Compaction Minor 合并部分 HFile;Major 合并全部 + 清理删除标记------Major 开销大,低峰执行
与 B+ 树对比 B+ 树一次查找 O(logN);LSM 可能查多层------点查 B+ 树快,海量写 LSM 快

** 追问链**:HBase 的数据模型是什么?→ Q3


Q3:HBase 的数据模型?列族怎么设计?

** 30 秒电梯版**

四维模型 (见 A 篇第三章):RowKey (行键,唯一+排序)+ Column Family (列族,物理分组)+ Column (列,动态+稀疏)+ Timestamp(多版本)。

列族设计三原则:

  1. 列族要少(1~3 个)------列族多 = MemStore 多 = Flush 频繁 = 小 HFile 多;
  2. 列族内列可动态------不用预定义,稀疏列不占空间;
  3. 访问模式相近的列放一族------一起读写的列放一起,减少 IO。

一句话总结 :RowKey 是唯一索引,列族是物理分组(1~3 个),列可动态稀疏,时间戳管多版本------HBase 是 schema-free 的列存 KV。

** 深挖版**

要点 说明
稀疏列的优势 空列不占空间------宽表(几千列)只有有值的列占空间,MySQL 宽表空列也占
多版本 默认保留 3 个版本------可查历史值,但空间翻倍,不需要就设 VERSIONS=1
列族与 HFile 每个列族独立 HFile------列族多 = HFile 多 = Compaction 压力大

** 追问链**:RowKey 怎么设计?→ Q5


Q4:HBase 和 MySQL 的区别?什么时候选 HBase?

** 30 秒电梯版**

维度 MySQL HBase
存储引擎 B+ 树(InnoDB) LSM-Tree
数据量 单表千万级 万亿行
写入 随机写(维护树) 顺序写(LSM)
查询 SQL/JOIN/事务 RowKey 点查/scan
索引 二级索引 只有 RowKey(原生无二级索引)
事务 ACID 单行事务
扩展 垂直为主 水平扩展(Region)

选 HBase 的场景:海量明细 KV(用户画像/消息记录/订单历史)、写多读少、毫秒点查、水平扩展。

一句话总结 :MySQL 管"关系和事务"(千万级),HBase 管"海量 KV 点查"(万亿级)------HBase 没有 JOIN 和二级索引,复杂查询走 Phoenix 或 ES。

** 深挖版**

要点 说明
Phoenix HBase 的 SQL 层------支持二级索引、JOIN、事务,但性能不如原生 API
与 MongoDB 对比 MongoDB 文档模型灵活,HBase KV+列族更"底层"------HBase 数据量上限更高,MongoDB 建模更灵活
强一致 HBase 单行读写强一致(Region 级)------比 Cassandra 的最终一致强

链条②:RowKey 与 Region 三连问

Q5:RowKey 设计的原则?怎么避免热点?

** 30 秒电梯版**

三原则 (见 A 篇 4.1):唯一 (唯一索引)、散列 (防热点)、短(16~100 字节,存在每个 Cell 里)。

热点问题 :RowKey 有序(自增 ID/时间戳开头)→ 新数据全写到最后一个 Region → 写热点。

三种规避:

  1. 加盐 :RowKey 前加随机前缀(hash(user_id)%16)------写入均匀,范围查询贵;
  2. 哈希:RowKey = MD5(user_id)------完全散列,牺牲范围查询;
  3. 反转:RowKey = 反转(user_id/时间戳)------保留部分范围能力。

一句话总结 :RowKey 设计是 HBase 第一设计决策------点查用哈希散列,范围查询用"散列前缀+有序后缀",有序 RowKey 是热点的根源。

** 深挖版**

要点 说明
时间戳取反技巧 Long.MAX_VALUE - timestamp------最新数据字典序排前面,scan 先拿最新
与 ClickHouse 分片键对比 同款热点思想:有序分片键/RowKey = 写热点------散列是通用的解法(19-B 篇事故二)
RowKey 长度 存在每个 Cell 里------100 字节 RowKey × 10 亿行 = 100GB 光 RowKey

** 追问链**:Region 是什么?→ Q6


Q6:Region 是什么?为什么要预分区?

** 30 秒电梯版**

Region :HBase 的水平分片------表按 RowKey 范围切成多个 Region,分布在不同 RegionServer(见 A 篇第五章)。Region 过大(默认 10GB)自动 Split。

预分区 :建表时预先指定 Split 点,创建多个 Region------不预分区 = 建表时只有 1 个 Region = 写入全打到 1 个 Region = 热点。

一句话总结 :Region 是 HBase 的分片单位,预分区是建表必做项------不预分区 = 单 Region 热点 = 写入瓶颈。

** 深挖版**

要点 说明
预分区数量 按节点数 × 每节点 Region 数估算(如 10 节点 × 20 = 200 Region)
Region 均衡 HMaster 负责 Region 分配/负载均衡------RegionServer 宕机后 Region 重新分配
与 ES 分片对比 ES 分片创建后不可变(reindex 扩),HBase Region 自动 Split------HBase 扩展更自动

** 追问链**:HBase 集群架构?→ Q7


Q7:HBase 集群架构?ZooKeeper 起什么作用?

** 30 秒电梯版**

三大组件:

  • HMaster :集群管理(Region 分配/负载均衡/DDL)------不处理读写;
  • RegionServer:管理 Region,处理读写、MemStore 刷盘、Compaction;
  • ZooKeeper :存 HMaster 地址、Region 元数据入口、集群状态------客户端先查 ZK 找 Region 位置,缓存后直连 RegionServer。

一句话总结 :HMaster 管调度、RegionServer 干活、ZooKeeper 当"通讯录"------ZK 挂了客户端找不到 Region 入口,集群不可用。

** 深挖版**

要点 说明
HMaster 高可用 多 HMaster 备份(ZK 选举 active)------HMaster 挂了不影响读写(只影响 DDL/均衡)
RegionServer 宕机 WAL 在 HDFS 上,Region 重新分配后重放 WAL------数据不丢
ZK 集群 3 节点 ZK 集群------ZK 单点是反模式(和 ClickHouse 同款教训,19-B 篇事故四)

链条③:时序库与选型三连问

Q8:时序数据库和 HBase/ClickHouse 的区别?监控数据存哪?

** 30 秒电梯版**

时序数据五特点(见 A 篇 6.1):带时间戳、只追加、按时间范围查、聚合为主、价值随时间衰减。

分工:

需求 选谁
监控指标 + 降采样 + 保留策略 时序库(InfluxDB/TDengine)
海量 KV 随机读写 HBase
海量聚合分析 ClickHouse
时序数据但无降采样需求 ClickHouse(也能存时序)

一句话总结 :监控指标用时序库(降采样+保留策略是核心),海量 KV 用 HBase,海量聚合用 ClickHouse------时序库的"降采样+自动删除"是其他库没有的。

** 深挖版**

要点 说明
降采样 1s 原始留 7 天 → 1min 聚合留 1 年 → 1h 聚合留 5 年------用精度换空间
Tag vs Field Tag 建索引(维度),Field 不建索引(值)------高基数维度别放 Tag
Prometheus 定位 监控告警专用(PromQL + 拉模型)------短期存储,长期存远程(InfluxDB/Thanos)

** 追问链**:降采样怎么实现?→ Q9


Q9:降采样和保留策略怎么设计?

** 30 秒电梯版**

降采样 :把高精度数据聚合为低精度------连续查询(Continuous Query)定时执行(如每 1min 算一次 avg/max/p99),结果写入低精度表。

保留策略 :数据保留时长------超期自动删除(原始 7 天、1min 聚合 1 年、1h 聚合 5 年)。

查询路由 :查最近 1 小时 → 原始数据;查最近 1 月 → 1min 聚合;查最近 1 年 → 1h 聚合------按时间范围路由到对应精度。

一句话总结 :降采样用连续查询定时聚合,保留策略超期自动删,查询按时间范围路由精度------"老数据不值钱,别用新数据的精度存"。

** 深挖版**

要点 说明
降采样的聚合函数 avg/max/min/p99/sum------监控场景 max/p99 比 avg 有用(avg 掩盖毛刺)
保留策略的存储收益 全量 1s 数据留 5 年 vs 降采样后------存储成本差 100 倍以上
与 ClickHouse TTL 对比 ClickHouse 也有 TTL(超期删除/降精度)------时序库把降采样做成一等公民

** 追问链**:时序库出过什么事故?→ Q10


Q10:HBase/时序库在生产上最容易踩的坑?

** 30 秒电梯版**

四大高频坑(详见第二章事故集):

  1. RowKey 有序导致写热点:时间戳开头,新数据全打最后一个 Region(事故一);
  2. 不预分区:建表 1 个 Region,写入瓶颈(事故二);
  3. 高基数维度放 Tag:user_id 放 Tag,时序库索引爆炸(事故三);
  4. 不降采样:1s 原始数据全量留 1 年,存储爆炸(事故四)。

一句话总结 :RowKey 要散列、建表要预分区、Tag 要低基数、数据要降采样------四条军规挡住 90% 的 HBase/时序库事故。

** 深挖版**

要点 说明
上线检查清单 RowKey 散列了吗?预分区了吗?Tag 基数检查了吗?降采样+保留策略配了吗?
监控四件套 Region 均衡度、Compaction 队列、时序库存储增长、Tag 基数
容量规划 HBase:数据量 × 副本数 / 单节点容量;时序库:原始数据量 × 保留天数 × 压缩率

二、生产事故案例集(五段式复盘)

事故一:RowKey 时间戳开头,写热点打爆单 Region

** 事故场景**

用户行为记录表 RowKey 设计为 timestamp_userId("按时间排序方便查最新")。上线后所有写入集中到最后一个 Region(新数据时间戳最大,字典序排最后),该 Region 所在 RegionServer CPU/IO 打满,写入 RT 从 5ms 恶化到 500ms,其他 RegionServer 空闲。

** 根因分析**

RowKey 有序导致写热点 (Q5):时间戳开头的 RowKey 字典序递增------新数据全写到最后一个 Region。和 ClickHouse 范围分片热点同款(19-B 篇事故二)------有序 RowKey/分片键 = 写热点的根源。

️ 预防方案

  1. RowKey 散列 :hash(userId)_timestamp 或反转时间戳------写入均匀分布;
  2. 加盐 :RowKey 前加 hash%16 前缀------16 个前缀均匀分布到各 Region;
  3. Region 均衡监控 :各 Region 写入量打点------倾斜度 >3 倍告警;
  4. RowKey 评审 :上线前评估 RowKey 的写入分布------有序 RowKey 直接打回。

** 事故解决**

  • 止血:手动 Split 热点 Region(临时缓解);
  • 根治 :RowKey 改 hash(userId)_反转(timestamp),数据迁移(新建表+双写切换);
  • 验证:写入均匀分布到 64 个 Region,单 Region RT 恢复 5ms。

** 一句话教训**

时间戳开头的 RowKey = 给最后一个 Region 上刑------有序 RowKey 是写热点的根源;散列前缀+有序后缀才是正解。


事故二:建表不预分区,单 Region 写入瓶颈

** 事故场景**

消息记录表建表时"先跑起来再说",没做预分区(默认 1 个 Region)。上线后写入 QPS 5000,全部打到 1 个 Region ------单 RegionServer 扛不住,写入 RT 恶化。等 Region 自动 Split 时,Split 速度追不上写入速度,持续热点 2 小时。

** 根因分析**

不预分区 (Q6):建表时 1 个 Region → 写入全集中 → 热点 → 自动 Split 追不上写入。预分区是建表必做项,"先跑起来"的代价是 2 小时写入瓶颈。

️ 预防方案

  1. 预分区必做 :建表时按 RowKey 分布预切 16~256 个 Region------按节点数 × 每节点 Region 数估算;
  2. 建表评审:无预分区的建表 DDL 直接打回;
  3. Region 数监控 :Region 数量 + 单 Region 大小打点------单 Region >5GB 告警;
  4. 压测验证 :上线前压测写入分布------确认均匀分布到各 Region。

** 事故解决**

  • 止血:手动预分区 + 数据迁移;
  • 根治:建表规范上线(预分区必做);全表排查未预分区的表(3 张);
  • 验证:预分区 64 Region,写入均匀分布,RT 稳定 5ms。

** 一句话教训**

不预分区 = 单 Region 热点 = 写入瓶颈------Split 追不上写入的速度;建表预分区是 HBase 的第一军规。


事故三:user_id 放 Tag,时序库索引爆炸

** 事故场景**

用户行为监控用 InfluxDB,开发把 user_id 放在 Tag 里("方便按用户查")。上线后用户量涨到 1000 万,Tag 基数 1000 万------InfluxDB 的 Tag 索引(TSI)膨胀到 50GB,内存占用暴涨,查询变慢,节点 OOM。

** 根因分析**

高基数维度放 Tag (Q8 深挖版):Tag 建索引------每个 Tag 值组合 = 一条时间序列 = 一个索引项 。user_id 基数 1000 万 = 1000 万条时间序列 = 索引爆炸。Tag 应该放低基数维度(host/region/服务名),高基数维度(user_id)放 Field。

️ 预防方案

  1. Tag 基数检查 :Tag 值数量 < 1 万------高基数维度放 Field;
  2. 建模评审 :时序数据建模时评估 Tag 基数------user_id/device_id 等高基数 ID 放 Field;
  3. 序列数监控 :SHOW SERIES 查时间序列数量------持续增长即告警;
  4. 按用户查的需求 :走应用层聚合或 ClickHouse(列存聚合强)------时序库不擅长高基数维度查询。

** 事故解决**

  • 止血:重启节点(临时);
  • 根治:user_id 从 Tag 改 Field,数据迁移;按用户查询改 ClickHouse;Tag 基数监控上线;
  • 验证:Tag 基数降到 200(host+region+服务名),索引 50MB,查询恢复毫秒级。

** 一句话教训**

user_id 放 Tag = 给索引喂 1000 万个值------Tag 建索引,高基数维度放 Tag = 索引爆炸;Tag 放低基数维度,高基数放 Field。


事故四:1s 原始数据全量留 1 年,存储爆炸

** 事故场景**

监控指标用 InfluxDB,开发"图省事"没配降采样和保留策略------1s 精度的原始数据全量保留。一年后数据量涨到 50TB,磁盘告警,查询变慢(扫描数据量太大)。

** 根因分析**

不降采样+不配保留策略 (Q9):1s 原始数据全量留 1 年 = 3153 万数据点/指标/年 × 1 万指标 = 3000 亿数据点。老数据价值低(没人查 1 年前的 1s 精度),但存储成本和新数据一样。

️ 预防方案

  1. 降采样必配 :1s 原始留 7 天 → 1min 聚合留 1 年 → 1h 聚合留 5 年------连续查询定时聚合;
  2. 保留策略必配 :超期自动删除------不配保留策略 = 数据无限增长;
  3. 存储增长监控 :磁盘占用趋势打点------增长超预期即告警;
  4. 查询路由 :按时间范围路由到对应精度------查老数据用聚合数据。

** 事故解决**

  • 止血:手动删除 1 年前的原始数据(释放 40TB);
  • 根治:降采样+保留策略上线;存储增长监控上线;
  • 验证:存储稳定在 2TB(降采样后),查询 RT 恢复。

** 一句话教训**

1s 原始数据全量留 1 年 = 用新数据的精度存老数据------老数据不值钱,降采样+保留策略是时序库的存储红利;不配 = 存储爆炸。


三、事故速查表

现象 可能根因 快速定位 根治方案
单 Region CPU/IO 打满 RowKey 有序写热点 各 Region 写入量对比 RowKey 散列;加盐/反转
写入瓶颈、Region 少 不预分区 Region 数量 预分区 16~256 Region
时序库索引膨胀、OOM 高基数维度放 Tag SHOW SERIES 查序列数 高基数放 Field;Tag 基数检查
存储无限增长 不降采样/不配保留策略 磁盘增长趋势 降采样+保留策略
读取慢 HFile 多(读放大) Compaction 队列;HFile 数 Major Compaction;布隆过滤器
RegionServer 宕机 硬件/网络故障 HMaster 日志;ZK 状态 WAL 恢复+Region 重分配(自动)
时序查询慢 扫描数据量大 查询时间范围+精度 查询路由到聚合数据

四、面试答题万能框架

#mermaid-svg-vIla8ogjJt150K8l{font-family:Microsoft YaHei;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vIla8ogjJt150K8l .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vIla8ogjJt150K8l .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vIla8ogjJt150K8l .error-icon{fill:hsl(220.5882352941, 100%, 98.3333333333%);}#mermaid-svg-vIla8ogjJt150K8l .error-text{fill:rgb(8.5000000002, 5.7500000001, 0);stroke:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-vIla8ogjJt150K8l .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vIla8ogjJt150K8l .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vIla8ogjJt150K8l .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vIla8ogjJt150K8l .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vIla8ogjJt150K8l .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vIla8ogjJt150K8l .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vIla8ogjJt150K8l .marker{fill:#0b0b0b;stroke:#0b0b0b;}#mermaid-svg-vIla8ogjJt150K8l .marker.cross{stroke:#0b0b0b;}#mermaid-svg-vIla8ogjJt150K8l svg{font-family:Microsoft YaHei;font-size:16px;}#mermaid-svg-vIla8ogjJt150K8l p{margin:0;}#mermaid-svg-vIla8ogjJt150K8l .label{font-family:Microsoft YaHei;color:#333;}#mermaid-svg-vIla8ogjJt150K8l .cluster-label text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-vIla8ogjJt150K8l .cluster-label span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-vIla8ogjJt150K8l .cluster-label span p{background-color:transparent;}#mermaid-svg-vIla8ogjJt150K8l .label text,#mermaid-svg-vIla8ogjJt150K8l span{fill:#333;color:#333;}#mermaid-svg-vIla8ogjJt150K8l .node rect,#mermaid-svg-vIla8ogjJt150K8l .node circle,#mermaid-svg-vIla8ogjJt150K8l .node ellipse,#mermaid-svg-vIla8ogjJt150K8l .node polygon,#mermaid-svg-vIla8ogjJt150K8l .node path{fill:#fff4dd;stroke:hsl(40.5882352941, 60%, 83.3333333333%);stroke-width:1px;}#mermaid-svg-vIla8ogjJt150K8l .rough-node .label text,#mermaid-svg-vIla8ogjJt150K8l .node .label text,#mermaid-svg-vIla8ogjJt150K8l .image-shape .label,#mermaid-svg-vIla8ogjJt150K8l .icon-shape .label{text-anchor:middle;}#mermaid-svg-vIla8ogjJt150K8l .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vIla8ogjJt150K8l .rough-node .label,#mermaid-svg-vIla8ogjJt150K8l .node .label,#mermaid-svg-vIla8ogjJt150K8l .image-shape .label,#mermaid-svg-vIla8ogjJt150K8l .icon-shape .label{text-align:center;}#mermaid-svg-vIla8ogjJt150K8l .node.clickable{cursor:pointer;}#mermaid-svg-vIla8ogjJt150K8l .root .anchor path{fill:#0b0b0b!important;stroke-width:0;stroke:#0b0b0b;}#mermaid-svg-vIla8ogjJt150K8l .arrowheadPath{fill:#0b0b0b;}#mermaid-svg-vIla8ogjJt150K8l .edgePath .path{stroke:#0b0b0b;stroke-width:2.0px;}#mermaid-svg-vIla8ogjJt150K8l .flowchart-link{stroke:#0b0b0b;fill:none;}#mermaid-svg-vIla8ogjJt150K8l .edgeLabel{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-vIla8ogjJt150K8l .edgeLabel p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-vIla8ogjJt150K8l .edgeLabel rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-vIla8ogjJt150K8l .labelBkg{background-color:rgba(243.9999999999, 220.9999999998, 255, 0.5);}#mermaid-svg-vIla8ogjJt150K8l .cluster rect{fill:hsl(220.5882352941, 100%, 98.3333333333%);stroke:hsl(220.5882352941, 60%, 88.3333333333%);stroke-width:1px;}#mermaid-svg-vIla8ogjJt150K8l .cluster text{fill:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-vIla8ogjJt150K8l .cluster span{color:rgb(8.5000000002, 5.7500000001, 0);}#mermaid-svg-vIla8ogjJt150K8l div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Microsoft YaHei;font-size:12px;background:hsl(220.5882352941, 100%, 98.3333333333%);border:1px solid hsl(220.5882352941, 60%, 88.3333333333%);border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vIla8ogjJt150K8l .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vIla8ogjJt150K8l rect.text{fill:none;stroke-width:0;}#mermaid-svg-vIla8ogjJt150K8l .icon-shape,#mermaid-svg-vIla8ogjJt150K8l .image-shape{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);text-align:center;}#mermaid-svg-vIla8ogjJt150K8l .icon-shape p,#mermaid-svg-vIla8ogjJt150K8l .image-shape p{background-color:hsl(-79.4117647059, 100%, 93.3333333333%);padding:2px;}#mermaid-svg-vIla8ogjJt150K8l .icon-shape .label rect,#mermaid-svg-vIla8ogjJt150K8l .image-shape .label rect{opacity:0.5;background-color:hsl(-79.4117647059, 100%, 93.3333333333%);fill:hsl(-79.4117647059, 100%, 93.3333333333%);}#mermaid-svg-vIla8ogjJt150K8l .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vIla8ogjJt150K8l .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vIla8ogjJt150K8l :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 被问 HBase / 时序库。
① 先给骨架 LSM-Tree 写读
流程+RowKey 三原则 30 秒讲清全貌。

② 按追问深挖 存储线:WAL /
MemStore / HFile /
Compaction 设计线:
RowKey 散列 / 预分区 /
列族 1~3 个 时序线:降采样 /
保留策略 / Tag 基数。

③ 落到生产视角 四条军规:
RowKey 散列 / 预分区必做
Tag 低基数 / 降采样必配。

④ 用事故收尾 写热点打爆 Regi
on / 索引爆炸 / 存储爆炸 有画面感的案例胜过背书。

加分技巧:

  • 谈 LSM-Tree 主动讲"写路径全程顺序 IO,读放大用 Compaction+布隆过滤器缓解"------读写不对称的完整理解;
  • 谈 RowKey 主动说"时间戳取反让最新数据排前面,scan 先拿最新"------设计技巧;
  • 谈时序库主动带"Tag 建索引、高基数放 Field、降采样用精度换空间"------时序建模三要点;
  • 谈选型主动讲"监控用时序库、海量 KV 用 HBase、聚合用 ClickHouse、交易用 MySQL"------四者分工;
  • 被问"遇到过什么 HBase 问题",用事故一(RowKey 热点)------"有序 RowKey 打爆单 Region"的教训最有设计教育意义。

五、与 A 篇的知识点映射

本篇题目/事故 A 篇《20-A-HBase与时序库详解》对应章节
Q1 LSM-Tree 写 2.1
Q2 读放大 2.2/2.3
Q3 数据模型 三章
Q4 vs MySQL 1.3/七章
Q5 RowKey 设计 4.1/4.2
Q6 Region/预分区 5.1/5.2
Q7 集群架构 5.1
Q8 时序库分工 6.1/七章
Q9 降采样 6.3
Q10 生产坑 全文军规汇总
事故一 RowKey 热点 4.2
事故二 不预分区 5.2
事故三 Tag 爆炸 6.2
事故四 不降采样 6.3

📌 结语 :HBase 面试题的尽头是"设计意识 "------RowKey 设计决定热点与否、预分区决定扩展性、列族数量决定 Compaction 压力;时序库面试题的尽头是"衰减意识 "------数据价值随时间衰减,降采样+保留策略把衰减变成存储红利。生产事故的尽头是"军规意识 "------RowKey 散列、预分区、Tag 低基数、降采样必配,每条军规都是一次事故的墓碑。
📌 配套阅读:

上一篇:《05-03-A-ClickHouse与OLAP详解.md》

 A 篇:《05-04-A-HBase与时序库详解.md》

下一篇:《05-05-A-对象存储与文件服务详解.md》

如果这篇文章对你有帮助,欢迎点赞、收藏、关注!🚀

相关推荐
Shadow(⊙o⊙)3 小时前
表的增删查改
数据库·mysql
+VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vue外卖点餐系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
怕浪猫4 小时前
分享一个做视频的skill,这条白板视频,每一笔都是代码画的
前端·javascript·面试
盟接之桥4 小时前
线束数字化--先进先出为什么总是停留在纸面上?
大数据·网络·数据库·人工智能·制造·ai编程
adinnet20265 小时前
预算管控:预算执行与偏差问数
大数据·数据库
弈栈录6 小时前
基于 Spring Boot 构建生产级 AI 应用平台
后端·面试·架构
Omics Pro7 小时前
Cell封面|衰老生物学开源AI工具包
数据库·人工智能·算法·机器学习·自然语言处理
Moment8 小时前
如果你在做 RAG,可能会需要 pdf-inspector
前端·后端·面试
卷福同学14 小时前
第一次当面试官有感
后端·面试