You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Flink中ListState与ValueState的性能选型疑问

Apache Flink中ListState与ValueState<List>的性能对比

在你的场景中——为每个Key存储最新100条记录,基于KeyedProcessFunction + RocksDB状态后端——两种实现都需要全量读取、修改后全量写入,但二者在性能上确实存在差异,具体分析如下:

存储结构差异

首先明确RocksDB对两种状态的存储方式:

  • ListState<Record>:Flink会将List中的每个Record作为独立的键值对存储,键的前缀是当前Key+状态名称+元素索引,每个元素单独序列化。
  • ValueState<List<Record>>:将整个List序列化为一个完整的字节数组,作为单个键值对存储在RocksDB中。

读写操作性能

读操作

两种方式都需要全量读取所有记录:

  • ListState需要从RocksDB读取100个独立的小条目,涉及多次随机IO;
  • ValueState只需读取一个包含100条记录的大条目,单次IO完成。
    在记录数量固定为100条的场景下,二者的读性能差异不大,但ValueState的单次IO会略占优势。

写操作

全量更新时的差异更明显:

  • ListState需要先删除旧的100个条目,再写入新的100个条目,总共涉及200次RocksDB操作;
  • ValueState仅需覆盖单个键值对,1次操作即可完成。
    因此写操作上ValueState的性能更优。

检查点性能(关键差异点)

文档推荐使用ListState的核心原因在于增量检查点的支持:

  • 当RocksDB开启增量检查点(这是生产环境的推荐配置)时,ListState只会将发生变化的元素写入检查点,无需全量同步;
  • 而ValueState<List<Record>>作为单个大值,每次检查点都需要将整个List全量序列化并写入,随着作业运行,检查点的开销会显著增加,甚至成为性能瓶颈。

总结建议

  • 若作业未开启增量检查点、检查点频率极低,且对实时读写性能要求极高,ValueState<List<Record>>的读写表现会更优;
  • 若作业使用RocksDB增量检查点(生产环境常规配置),ListState在检查点阶段的性能优势会抵消读写时的微小差异,长期运行更稳定,也更符合Flink的状态设计规范。

两种实现代码示例

// 使用ListState的实现
ListState<Record> listState;
Iterable<Record> records = listState.get();
List<Record> list = new ArrayList<>();
// 遍历迭代器并添加到list,加入新记录后截断到100条
records.forEach(list::add);
list.add(newRecord);
if (list.size() > 100) {
    list = list.subList(list.size() - 100, list.size());
}
listState.update(list);

// 使用ValueState的实现
ValueState<List<Record>> valueState;
List<Record> list = valueState.value();
if (list == null) {
    list = new ArrayList<>();
}
list.add(newRecord);
if (list.size() > 100) {
    list = list.subList(list.size() - 100, list.size());
}
valueState.update(list);

内容的提问来源于stack exchange,提问作者Liang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 11:27:22