可用的State Backend

Flink提供三种开箱即用的State Backend:

  • HashMapStateBackend
  • EmbeddedRocksDBStateBackend

HashMapStateBackend

HashMapStateBackend在java堆上保存数据,健值对的状态和windows函数使用hashtable存储值或者触发器。

HashMapStateBackend优势:

  • job的状态(state)很大,window很长,状态的键值对很大
  • 所有高可用性设置

还建议将托管内存设置为零。 这将确保为 JVM 上的用户代码分配最大量的内存。 与 EmbeddedRocksDBStateBackend 不同,HashMapStateBackend 将数据作为对象存储在堆上,因此重用对象是不安全的。

EmbeddedRocksDBStateBackend

EmbeddedRocksDBStateBackend 将动态数据保存在 RocksDB 数据库中,该数据库(默认情况下)存储在 TaskManager 本地数据目录中。 与在 HashMapStateBackend 中存储 java 对象不同,数据存储为序列化的字节数组,主要由类型序列化器定义,因此导致键的比较是按字节进行的,而不是使用 Java 的 hashCode() 和 equals() 方法。

EmbeddedRocksDBStateBackend 始终执行异步快照。

EmbeddedRocksDBStateBackend优缺点

缺点:

  • 由于 RocksDB 的 JNI 桥接 API 基于 byte[],每个键和每个值支持的最大大小为 2^31 字节。 在 RocksDB 中使用合并操作的状态(例如 ListState)可以静默地累积大于 2^31 字节的值大小,然后在下一次检索时失败。 这是目前 RocksDB JNI 的一个限制。

优点:

  • 具有非常大状态、长窗口、大键/值状态的作业(比HashMapStateBackend 更好的处理更大的状态)
  • 所有高可用性设置。

注意:EmbeddedRocksDBStateBackend可以保留的状态大小仅受磁盘空大小的限制。与将状态保存在内存中的 HashMapStateBackend 相比,这允许保存非常大的状态。 但是,这也意味着使用此状态后端的最大吞吐量会更低。 此后端的所有读取写都必须通过反序列化或者序列化来查询或者写入状态对象,这也比始终使用堆上表示更昂贵。由于反序列化,EmbeddedRocksDBStateBackend 可以安全地重用对象。

总结

在 HashMapStateBackend 和 RocksDB 之间做出选择时,它是性能和可伸缩性之间的选择。 HashMapStateBackend 非常快,因为每个状态访问和更新都对 Java 堆上的对象进行操作; 但是,状态大小受集群内可用内存的限制。 另一方面,RocksDB 可以根据可用磁盘空间进行扩展,并且是唯一支持增量快照的状态后端。 但是,每个状态访问和更新都需要(反)序列化并可能从磁盘读取,这导致平均性能比内存状态后端慢一个数量级。