Flink 使用Memory State导致OOM问题与解决

一、现象

1.1 程序现象

程序是处理一个业务由2个表、4条数据、互相Join形成2条结果。Flink读取Kafka。模拟数据程序持续往Kafka插入数据,在TaskManager只有较低内存时,模拟了2000次插入(8000条数据时),Flink的TaskManager就发生了OOM问题。使用jstat -gcutil
(遇到一个小问题root用户无法查看yarn用户的jvm jstat信息 找不到socket文件,
Unable to open socket file: target process not responding or HotSpot VM not loaded
需要切换过去。切换yarn用户遇到 资源不够。需要修改linux配置https://www.cnblogs.com/taiguyiba/p/7868894.html)

查看JVM进程发现Old区域在年轻代做垃圾回收时,每次持续5%左右的增长,直到达到100%的状态。即使做FGC,Old的内存也降不下去。持续一段时间FGC无响应后,则被JobManager认为该container中的TaskManager无响应,并移除这个TaskManager。直到整个应用的TaskManager都被移除。最后程序Finished (异常退出崩溃)。

二、解决

2.1 加内存

最初步定位是的内存不够,于是一开始就想着给TaskManager加内存。直到加到16G内存。但是OOM的问题丝毫没有改善。在处理24条数据后。Old区用完且下降。持续FGC。异常退出。

2.2 分析Dump文件

在16G内存TaskManager情况下。dump出Old区大概为90%的情况下的堆文件 (11G)。将dump文件拷贝到一台8G的windows机器,使用MAT工具进行分析,但是一直分析失败。windows机器不够用。

解决:在linux机器上使用 Mat Linux版。使用命令行工具进行分析。(参考:

### Flink SQL 中聚合函数的状态保存机制 在 Flink SQL 中,使用聚合函数(如 `COUNT`, `SUM`, `AVG` 等)时,Flink 会通过内部的状态管理机制来保存中间计算结果。这种状态通常以键控状态(Keyed State)的形式存储在内存中,并且可以通过 RocksDB 等持久化后端进行存储[^5]。当执行聚合操作时,例如 `COUNT(DISTINCT b)`,Flink 会为每个分组键维护一个独立的状态实例。这些状态实例用于记录每个分组内的聚合值。 对于复杂的聚合场景(如包含多个 `COUNT(DISTINCT ...)` 的查询),Flink 会为每个 `DISTINCT` 聚合创建单独的状态实例。这意味着如果查询中有多个 `COUNT(DISTINCT ...)`,那么将会有多个状态实例被创建和维护。这种设计虽然提高了灵活性,但也可能导致状态占用的内存增加,尤其是在数据分布不均匀或分组键数量较多的情况下[^5]。 ### 长时间运行引发 OOM 问题的原因及解决方案 长时间运行的 Flink 任务可能会因为状态持续增长而导致 OutOfMemory (OOM) 问题。主要原因包括: 1. **状态无限增长**:如果聚合操作涉及大量的分组键,或者某些分组键的数据量特别大,那么状态可能会持续增长,最终超过可用内存的限制。 2. **未配置状态 TTL**:Flink 提供了状态时间生存期(TTL,Time-to-Live)机制,允许用户定义状态的过期时间。如果没有正确配置状态 TTL,过期的状态不会被清理,从而导致内存占用不断增加[^1]。 3. **内存分配不足**:即使状态大小合理,但如果任务的内存配置不足,也可能导致 OOM 问题。 #### 解决方案 - **启用增量检查点**:通过设置 `execution.checkpointing.incremental=true`,可以减少每次检查点的开销,并提高任务的恢复效率[^1]。 - **配置状态 TTL**:通过设置 `state.retention.time.min` 和 `state.retention.time.max`,确保过期状态能够被及时清理。例如,可以将状态保留时间设置为 15 天到 20 天之间[^1]。 - **优化状态存储后端**:使用 RocksDB 作为状态后端可以有效降低内存压力,因为它将大部分状态存储在磁盘上,仅将热点数据保留在内存中。 - **调整并行度**:适当增加任务的并行度可以分散状态的压力,避免单个 TaskManager 承担过多的状态。 - **监控和调优**:通过 Flink 的监控系统,实时跟踪任务的状态大小、内存使用情况和垃圾回收频率,及时发现潜在问题[^4]。 ### 示例代码:配置状态 TTL 和增量检查点 ```sql SET 'execution.checkpointing.incremental' = 'true'; SET 'state.ttl' = '7 days'; SET 'state.backend' = 'rocksdb'; ``` ### 注意事项 在实际应用中,需要根据业务需求和数据特性合理配置状态管理参数。例如,对于高并发的实时计算场景,可能需要更频繁的检查点间隔(如 10 分钟)和更大的超时时间(如 60 分钟)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值