Flink在何时进行操作状态的序列化/反序列化?是在每次get/update时还是基于检查点?状态后端是否有影响? 我怀疑,在具有多样化键(数百万)和每个键每秒数千个事件的键控流情况下,序列化/反序列化可能是一个大问题。我对吗?
您的假设是正确的。这取决于状态后端。在JVM堆上存储状态的后端(MemoryStateBackend和FSStateBackend)在常规读/写访问时不对状态进行序列化,而是将其保留为堆上的对象。虽然这可以实现非常快速的访问,但您显然受制于JVM堆的大小,并可能面临垃圾回收问题。当执行检查点时,对象会被序列化并持久化以便在发生故障时进行恢复。相比之下,RocksDBStateBackend将所有状态作为字节数组存储在嵌入式RocksDB实例中。因此,它会对每个读/写访问键的状态进行序列化/反序列化。您可以通过选择适当的状态原语(ValueState、ListState、MapState等)来控制“有多少”状态被序列化。例如,ValueState总是作为整体进行序列化/反序列化,而MapState.get(key)仅对键进行序列化(用于查找),并对返回的键值进行反序列化。因此,您应该使用MapState而不是ValueState>。其他状态原语也需要类似的考虑。RocksDBStateBackend通过将文件复制到持久性文件系统来对其状态进行检查点。因此,当执行检查点时,不涉及任何额外的序列化。