HBase 写数据流程:又快又不丢,靠的是”先记日志、再写内存、最后刷盘”
HBase 写入数据,面临两个矛盾的要求:
- 要快:高吞吐写入,不能等磁盘 IO
- 要可靠:RegionServer 宕机了,数据不能丢
HBase 的解法是三步走:
- 先写日志(WAL)——记下来,保证不丢
- 再写内存(MemStore)——快,写完就返回客户端
- 最后异步刷盘——攒够了再写到磁盘
核心逻辑:写日志(慢但可靠)+ 写内存(快但易失)→ 两者结合 = 又快又不丢。
写一条数据,HBase 经历了什么?
1. 客户端发请求 → RegionServer
2. 写 WAL(预写日志,HDFS 持久化)
3. 写 MemStore(内存)
4. 返回客户端"成功"
5. (异步)MemStore 满了 → 刷盘成 StoreFile
6. (异步)小 StoreFile 合并成大文件(Compaction)
客户端在第 4 步就收到成功了,第 5、6 步是后台慢慢做的。
graph TD
A[客户端] -->|1. 发送写请求| B[目标 RegionServer]
B -->|2. 写入预写日志WAL/HLog<br/>同步到 HDFS 多副本| C[HLog 持久化]
C -->|3. 写入内存缓存MemStore<br/>按 RowKey 排序| D[MemStore]
D -->|4. 立即反馈| A
D -->|5. 触发刷盘条件?<br/>大小/时间阈值等| E{判断}
E -->|是| F[MemStore 刷盘<br/> 生成 StoreFile]
E -->|否| D
F -->|6. 小文件数量/大小达标?| G{判断}
G -->|是| H[StoreFile 合并<br/>Minor/Major Compaction]
G -->|否| F
H -->|7. Region 大小超限?| I{判断}
I -->|是| J[Region 拆分<br/> 子 Region 负载均衡]
I -->|否| H
J -->|8. 新 Region 分配到其他 RegionServer| B
第一步:定位 RegionServer
写数据之前,客户端要先知道”这条数据写到哪个 RegionServer 上”。
流程跟读数据一样:
- 客户端连 ZooKeeper,找
hbase:meta 表的位置
- 查
hbase:meta 表,根据 RowKey 定位目标 Region 和 RegionServer
- 客户端直连那个 RegionServer
定位完成之后,后面的写操作都在这个 RegionServer 上完成。
第二步:写 WAL——“我先记下来,保证不丢”
WAL(Write-Ahead Log)是 HBase 数据可靠性的第一道防线。