记录一次问题解决的过程。
生产中有个设备运行状态持续时间计算的任务,当设备的数据量由1000+加到8000+,每秒采集一次的设备的状态和各项指标发送到kafka给到flink进行处理。状态持续时间计算的算子中状态的checkpoint频繁超时,监控显示当个TaskManager的状态达2G,RocksDB的写入延迟飙升到几百毫秒。业务方反馈统计滞后越来越严重。
-
定位根因 :通过Flink UI中的SubTask分析State Size,发现
MapState占了90%的状态量。检查代码发现,每次状态变更都追加时间戳,但从未清理过期数据------实际上只需要知道当前状态的开始时间,完全不需要保存历史时间戳。 -
重构状态结构 :将
MapState<Long, Long>改为ValueState<StatusRecord>,其中StatusRecord只存两个字段:currentStatus和statusStartTime。这样每个设备只存一个对象,状态量从每台上千个时间戳骤降到1个。 -
设置TTL :使用
StateTtlConfig为ValueState设置24小时TTL,并将cleanupStrategies设为基于RocksDB的Compaction过滤,避免由于惰性清理导致状态无限残留。 -
优化RocksDB参数 :将
state.backend.rocksdb.writebuffer.size从32MB调到64MB,开启增量Checkpoint,缩短快照时间。
通过修改以上参数,重启flink集群及任务后,问题得到了解决。