1. 什么是状态后端?
状态后端(State Backend) 决定了 Flink 状态(state)存在哪、怎么存。
- 状态可以在 Java 堆上(on-heap) 或 堆外/磁盘(off-heap / on-disk)。
- 某些后端由 Flink 托管内存 ,必要时会 溢写到磁盘 ,让你的作业能持有非常大的状态。
- 默认后端 由集群的
flink-conf.yaml
决定;也可 按作业覆盖。
一句话:你写的算子/窗口/连接器都可能有状态,状态后端就是这堆"账本"的存放与管理方式。
2. 常见的两大类后端(Flink 1.15+ 的主流形态)
名称可能随版本演进,但核心理念稳定:堆内 HashMap vs 嵌入式 RocksDB。
2.1 HashMapStateBackend(堆内)
- 工作位置:JVM 堆(on-heap)。
- 特点 :读写快 、实现简单、延迟很低;受 JVM 内存与 GC 影响。
- 适用 :小/中状态(几百 MB ~ 数 GB)、延迟敏感的实时任务、资源相对充裕的场合。
- 注意:超大状态易触发频繁 GC 或 OOM;要给 TaskManager 足够堆内存,并关注 GC 配置。
2.2 EmbeddedRocksDBStateBackend(RocksDB)
- 工作位置:RocksDB(本地磁盘 + 页缓存,属于 off-heap/on-disk)。
- 特点 :支持远超内存 的大状态、可做增量 checkpoint ;但序列化与磁盘 IO 让延迟和吞吐相对堆内慢。
- 适用 :中/大/超大状态(数 GB ~ TB 级)、需要稳定可恢复性、对延迟要求不极致的批流或大窗口任务。
- 注意:需要为本地盘(最好是 NVMe)与操作系统页缓存留资源;合理配置压缩、并行 compaction 等。
3. 后端选型:怎么选最合适?
维度 | HashMapStateBackend | EmbeddedRocksDBStateBackend |
---|---|---|
延迟 | 低 | 中等(序列化/磁盘 IO) |
吞吐 | 高 | 中-高(依赖磁盘/页缓存) |
状态规模 | 小--中 | 中--超大 |
内存/GC | 受 JVM 堆 & GC 影响 | 几乎不受 JVM 堆限制 |
Checkpoint 大小 | 往往较大(全量) | 支持增量,CK 更小更快 |
调优复杂度 | 低 | 中--高(RocksDB 参数较多) |
适配场景 | 风控/告警/实时特征 | 大窗口、CEP、海量 keyed state |
经验法则
- 延迟极敏感 & 状态不算大 → 选 HashMap。
- 状态很大/要增量 CK/可接受稍高延迟 → 选 RocksDB。
- 不确定? 先上 HashMap 跑通;一旦出现内存/GC/规模瓶颈,再迁到 RocksDB。
4. 配置方式:集群级与作业级
4.1 集群级(flink-conf.yaml
)
yaml
# 集群默认状态后端(两种常见写法之一,具体以版本为准)
state.backend: hashmap # 或者:state.backend: rocksdb
# Checkpoint 基础(建议配上,让状态可恢复)
execution.checkpointing.mode: EXACTLY_ONCE
execution.checkpointing.interval: 10s
execution.checkpointing.timeout: 2m
execution.checkpointing.max-concurrent-checkpoints: 1
execution.checkpointing.unaligned.enabled: true
# 若使用文件系统存放 checkpoint
execution.checkpointing.storage: filesystem
execution.checkpointing.dir: hdfs:///flink/ckpt/<job>
4.2 作业级(按 job 覆盖默认)
java
import org.apache.flink.configuration.Configuration;
import org.apache.flink.runtime.state.StateBackendOptions;
Configuration config = new Configuration();
// 覆盖为 HashMap
config.set(StateBackendOptions.STATE_BACKEND, "hashmap");
env.configure(config);
// 也可以在此处顺带覆盖 checkpoint 存储
// config.set(CheckpointingOptions.CHECKPOINT_STORAGE, "filesystem");
// config.set(CheckpointingOptions.CHECKPOINTS_DIRECTORY, "hdfs:///flink/ckpt/my-job");
// env.configure(config);
备注:新旧版本在 API 与 key 名称上可能略有变化,但思路一致:集群有默认,作业可覆盖。
5. 与 Checkpoint/Savepoint 的关系
- HashMap :通常做全量 checkpoint,简单但体积可能较大。
- RocksDB :支持增量 checkpoint(只传变化),能显著降低 CK 大小与耗时。
- Savepoint :算"可携带的快照",用于升级/迁移;两种后端都支持,从 savepoint 恢复时要保证序列化兼容 与状态映射一致。
6. 性能调优与最佳实践
6.1 HashMapStateBackend 调优
- JVM 堆:给够!避免频繁 Full GC。
- GC:G1/Parallel 视版本与业务选择;监控 GC 停顿时间与吞吐。
- Key/Value 序列化:使用高效序列化器(POJO、Avro、Kryo 配置优化)。
- State TTL:合理的 TTL 和清理策略,避免老旧状态堆积。
6.2 EmbeddedRocksDBStateBackend 调优
-
本地磁盘 :优先 NVMe;将
temp
或 RocksDB 路径放到独立数据盘。 -
RocksDB 选项(不同版本暴露方式不同,思路如下):
- 压缩 :
LZ4
通常是较好平衡;数据压缩可降低 IO 与 CK 体积。 - 并行:增大 compaction 线程,避免长尾。
- Block Cache/Write Buffer:平衡读写负载与内存占用。
- 压缩 :
-
增量 CK :开启
execution.checkpointing.incremental: true
(若版本/后端支持)。 -
非对齐 CK:在反压下强烈推荐,显著降低 CK 时间。
-
本地备份 :
execution.checkpointing.local-backup.enabled: true
,加速从故障中恢复。 -
文件合并(1.20+ 实验):减少小文件洪泛,缓解 NN/S3 元数据压力。
7. 迁移与兼容性
-
HashMap → RocksDB:常见从"小状态"长成"大状态"的升级路线;需重新评估延迟与磁盘资源。
-
RocksDB → HashMap:当状态规模下降、追求更低延迟时可考虑回迁。
-
有序步骤:
- 打
savepoint
(或确认外部化 CK); - 变更后端配置;
- 从 savepoint/CK 恢复;
- 验证状态一致与延迟指标。
- 打
-
序列化兼容:字段变更、类名变更要谨慎;建议使用稳定 Schema(如 Avro/Protobuf)。
8. 常见问题(FAQ)与排查清单
Q1:内存不够 / GC 抖动严重怎么办?
- 先检查是否 HashMap 后端 + 大状态 ;若是,考虑迁到 RocksDB。
- 减少状态体积:Key 设计、TTL、去冗余;JVM 参数与 GC 调优。
Q2:Checkpoint 很慢 / 超时?
- 观察是否有反压 ;若有,启用非对齐。
- 使用 增量 CK(RocksDB) ,提高
timeout
;确认 HDFS/S3 带宽与 NN/S3 元数据无瓶颈。
Q3:恢复很慢?
- 开启 本地备份;缩小 CK 间隔与增量大小;确保磁盘与网络带宽充足。
Q4:小文件太多、NameNode/S3 压力大?
- Flink 1.20+ 启用文件合并;调大 CK 间隔、优化 sink 滚动策略。
Q5:从 savepoint 恢复失败(状态无法映射)?
- 检查并发与算子链路是否一致;必要时使用 映射规则(state mapping) 或保持拓扑稳定后再升级。
9. 可直接抄用的配置模板
9.1 HashMap(低延迟,小/中状态)
yaml
# 状态后端
state.backend: hashmap
# Checkpoint 基础
execution.checkpointing.mode: EXACTLY_ONCE
execution.checkpointing.interval: 5s
execution.checkpointing.timeout: 2m
execution.checkpointing.max-concurrent-checkpoints: 1
execution.checkpointing.unaligned.enabled: true
# 存储
execution.checkpointing.storage: filesystem
execution.checkpointing.dir: hdfs:///flink/ckpt/<job>
execution.checkpointing.num-retained: 3
9.2 RocksDB(大状态 + 增量 CK)
yaml
# 状态后端
state.backend: rocksdb
# Checkpoint 基础
execution.checkpointing.mode: EXACTLY_ONCE
execution.checkpointing.interval: 10s
execution.checkpointing.min-pause: 2s
execution.checkpointing.timeout: 3m
execution.checkpointing.max-concurrent-checkpoints: 1
execution.checkpointing.incremental: true
execution.checkpointing.unaligned.enabled: true
execution.checkpointing.local-backup.enabled: true
execution.checkpointing.local-backup.dirs: /data/flink/localState
# 存储
execution.checkpointing.storage: filesystem
execution.checkpointing.dir: hdfs:///flink/ckpt/<job>
execution.checkpointing.num-retained: 3
# 1.20+(实验)文件合并
execution.checkpointing.file-merging.enabled: true
execution.checkpointing.file-merging.max-file-size: 256mb
execution.checkpointing.file-merging.max-space-amplification: 2.0
execution.checkpointing.file-merging.across-checkpoint-boundary: true
9.3 按作业覆盖(Java)
java
// 覆盖为 HashMap
Configuration config = new Configuration();
config.set(StateBackendOptions.STATE_BACKEND, "hashmap");
env.configure(config);
// 也可改为 RocksDB:
// config.set(StateBackendOptions.STATE_BACKEND, "rocksdb"); env.configure(config);
10. 实战建议(落地清单)
- 先确定画像:延迟优先 or 大状态优先。
- 评估资源:JVM 堆/本地盘/NVMe/网卡带宽;HDFS/S3 指标与限流。
- 打通 CK:Exactly-once + 外部化;非对齐用于反压场景;增量 CK(RocksDB)。
- 监控与告警:CK 时长、失败率、反压时间、GC、磁盘 IO、NN/S3 小文件指标。
- 演练恢复:定期从 savepoint/CK 恢复演练,验证 RPO/RTO。
- 版本策略:升级前打 savepoint;变更后端或并发时验证状态映射。
结语
状态后端的本质是在性能、成本与可恢复性之间的取舍。
- 追求极致延迟 → HashMap;
- 追求极致规模与恢复韧性 → RocksDB;
- 通过 非对齐/增量 CK/本地备份/文件合并 等手段,将你的作业调到最合适的"甜点区"。