1. 迁移必须知道的"硬规则"
旧版本(TM < 1.10 / JM < 1.11)很多内存参数即使不配也能跑,因为默认值很全。
新版本开始,至少要显式配置下面这些中的一类,否则会直接失败:
TaskManager 至少配置一项:
taskmanager.memory.flink.sizetaskmanager.memory.process.sizetaskmanager.memory.task.heap.size+taskmanager.memory.managed.size
JobManager 至少配置一项:
jobmanager.memory.flink.sizejobmanager.memory.process.sizejobmanager.memory.heap.size
Flink 官方默认配置为了"开箱即用",从 1.10 起默认写了:
taskmanager.memory.process.size(TaskManager)jobmanager.memory.process.size(JobManager)
因此你的迁移策略最好也围绕它们展开。
2. 新内存模型一句话理解
以前你配 taskmanager.heap.size,名字叫 heap,但里面其实混了很多非 heap 的东西(network、off-heap、cutoff 等),属于"一个大桶"。
现在把桶拆细了:Flink 会把总内存拆成多个明确组件(task heap、framework heap、managed、network、metaspace、overhead、off-heap 等),并且支持你更精确控制其中一部分。
结论:新模型更可控,但也更容易因"组合不成立"而报错。
3. TaskManager(<=1.9 → >=1.10)迁移要点
3.1 被彻底移除的配置(写了也会被忽略)
-
taskmanager.memory.fraction- 不要再指望它生效了
- 新替代:
taskmanager.memory.managed.fraction(注意语义不同)
-
taskmanager.memory.off-heap- managed memory 不再支持 on-heap,现在总是 off-heap
-
taskmanager.memory.preallocate- 预分配不再支持,managed memory 总是懒分配
另外,容器 cut-off(Yarn 时代常见)对 TaskManager 也不再生效:
containerized.heap-cutoff-ratiocontainerized.heap-cutoff-min
3.2 旧配置仍能用,但属于"兼容解释"(建议尽快替换)
以下是"旧字段写着还能跑"的映射逻辑:
-
taskmanager.heap.size- standalone 部署:解释为
taskmanager.memory.flink.size - 容器化(Yarn/K8S):解释为
taskmanager.memory.process.size
- standalone 部署:解释为
-
taskmanager.memory.size- 解释为
taskmanager.memory.managed.size
- 解释为
-
network 三件套旧名改新名(语义基本一致)
taskmanager.network.memory.min→taskmanager.memory.network.mintaskmanager.network.memory.max→taskmanager.memory.network.maxtaskmanager.network.memory.fraction→taskmanager.memory.network.fraction
建议做法:把旧字段全部替换成新字段,别长期靠兼容层。
3.3 "总内存"迁移:从 heap.size 到 flink.size / process.size
旧的 taskmanager.heap.size / taskmanager.heap.mb 虽然叫 heap,但实际是"Flink 总内存桶"。
新版本你应该按部署形态选一个:
- standalone(非容器):优先用
taskmanager.memory.flink.size - Yarn/K8S(容器):优先用
taskmanager.memory.process.size
如果你只配置了总内存(flink.size 或 process.size),那么 JVM Heap 会被推导为"剩余部分":总内存减去 network、managed、framework、metaspace、overhead 等之后剩下多少就是 heap。
3.4 managed memory 迁移:最关键、也最容易踩坑的一块
旧时代 managed memory 可以 on-heap/off-heap,还能 preallocate,还能用 taskmanager.memory.fraction 计算。
新时代变化很大:
-
managed memory 总是 off-heap
-
managed memory 使用的是 native memory(不是 direct memory)
- 因此它不再算进 JVM Direct Memory limit
-
managed memory 总是 懒分配
-
fraction 计算要用新字段:
taskmanager.memory.managed.fraction- 语义:当
taskmanager.memory.managed.size没显式设置时,managed = total flink memory * fraction
- 语义:当
RocksDBStateBackend 的强关联
如果你使用 RocksDBStateBackend(流作业很常见):
-
RocksDB 的 native 内存消耗现在应该 算在 managed memory 里
-
Flink 会用 managed memory 去 限制 RocksDB 内存分配,目的是减少容器被 Yarn/K8S 杀掉的概率
-
你也可以禁用该控制:
state.backend.rocksdb.memory.managed: false- 但禁用后更容易出现容器 OOMKill,需要你自己兜住 native 内存峰值
经验建议:只要你用 RocksDB,就优先把 managed memory 配清楚,别全靠默认推导。
3.5 TaskManager 迁移示例(容器化推荐模板)
yaml
# 推荐:容器化场景直接控制总进程内存
taskmanager.memory.process.size: 8192m
# managed memory:RocksDB/Sort/Hash/State 相关都吃它
taskmanager.memory.managed.size: 2048m
# 或者用 fraction(不和 size 同时使用)
# taskmanager.memory.managed.fraction: 0.25
# 网络内存:shuffle/反压敏感
taskmanager.memory.network.min: 512m
taskmanager.memory.network.max: 1024m
taskmanager.memory.network.fraction: 0.1
# 如果你希望更精准控制算子堆(例如 heavy UDF/JSON 对象)
# taskmanager.memory.task.heap.size: 4096m
4. JobManager(<=1.10 → >=1.11)迁移要点
JobManager 旧时代常用:
jobmanager.heap.sizejobmanager.heap.mb
但在容器化部署(Yarn/K8S)下,它们实际也混进了 off-heap 等内容,并且会被 container cut-off 影响。
4.1 旧字段的兼容映射
如果你还在用旧字段且没配新字段,Flink 会做兼容转换:
- standalone:
jobmanager.heap.size→jobmanager.memory.heap.size - 容器化(Yarn/K8S):
jobmanager.heap.size→jobmanager.memory.process.size
推荐你直接改成新字段,避免未来彻底移除。
4.2 container cut-off 被移除
旧配置:
containerized.heap-cutoff-ratiocontainerized.heap-cutoff-min
在 1.11 后对 JobManager 也不再生效了。新模型用更具体的组件去覆盖这些"不可控开销":
JobManager 可用的新补偿项:
jobmanager.memory.off-heap.sizejobmanager.memory.jvm-metaspace.size- JVM overhead(相关配置项)
4.3 JVM 进程内存限制的新变化(对排查很有用)
从 1.10 开始,Flink 会为 TaskManager 设置 JVM Metaspace、JVM Direct Memory 的 limit(通过 JVM 参数)。
从 1.11 开始,Flink 也会为 JobManager 设置 JVM Metaspace limit。并且你可以选择让 JobManager 也启用 direct memory limit:
jobmanager.memory.enable-jvm-direct-memory-limit: true
意义:更容易暴露 metaspace/direct memory 泄漏,减少"容器突然 OOMKill 但 JVM 没报错"的黑盒情况。
4.4 JobManager 迁移示例(容器化推荐模板)
yaml
jobmanager.memory.process.size: 2048m
# 如果你想更精确控制 JM 的 heap(例如大量 metadata / REST / checkpoint coordination)
# jobmanager.memory.heap.size: 1024m
# 可选:开启 direct memory limit 便于定位泄漏(需要你能接受更早暴露 OOM)
# jobmanager.memory.enable-jvm-direct-memory-limit: true
5. 迁移对照表:旧字段怎么改最直接
TaskManager:
taskmanager.heap.size→ 容器用taskmanager.memory.process.size,非容器用taskmanager.memory.flink.sizetaskmanager.memory.size→taskmanager.memory.managed.sizetaskmanager.network.memory.*→taskmanager.memory.network.*- 删除:
taskmanager.memory.fraction、taskmanager.memory.off-heap、taskmanager.memory.preallocate - 忽略:
containerized.heap-cutoff-*
JobManager:
jobmanager.heap.size→ 容器用jobmanager.memory.process.size,非容器用jobmanager.memory.heap.size- 忽略:
containerized.heap-cutoff-* - 可补偿:
jobmanager.memory.off-heap.size、jobmanager.memory.jvm-metaspace.size、overhead
6. 一套"稳妥迁移步骤"(照做基本不翻车)
-
先确定部署形态:standalone 还是 Yarn/K8S
-
把旧的
taskmanager.heap.size、jobmanager.heap.size全部替换为新字段- 容器化优先选
*.memory.process.size
- 容器化优先选
-
明确是否使用 RocksDBStateBackend
- 用 RocksDB:显式配置
taskmanager.memory.managed.size或managed.fraction
- 用 RocksDB:显式配置
-
检查 network 三件套是否还合理
- 并发/分区数变大时,network 不够会非常明显
-
启动失败时优先排查组合冲突
- fraction 是否 > 1
- min 是否 > max
- 同时写死了多个组件导致"剩余 heap 为负数"
-
容器 OOMKill 时,优先补 native/overhead,而不是盲目加 heap
- 特别是 RocksDB checkpoint/savepoint 峰值场景
7. 常见坑位提示
- 旧的
taskmanager.memory.fraction被移除后,有人误以为managed.fraction等价替换
实际语义不同,迁移时通常需要重新评估比例 - 只配了
process.size但没有意识到 "heap 是剩余推导"
你一旦把 managed/network/metaspace/overhead 配大了,heap 可能被挤得很小,引发 heap OOM 或频繁 GC - RocksDB 相关内存没算进 managed,最容易被容器杀
新模型就是为了把这块纳进可控范围,别绕回老路