Flink、Kafka 和 JDBC 接收器

时间:2021-06-26 21:28:52

标签: jdbc apache-kafka apache-flink flink-streaming

我有一个 Flink 1.11 作业,它使用来自 Kafka 主题的消息、对它们进行键控、过滤它们(keyBy 后跟自定义 ProcessFunction),并通过 JDBC 接收器将它们保存到数据库中(如下所述:https://ci.apache.org/projects/flink/flink-docs-release-1.11/dev/connectors/jdbc.html )

Kafka 消费者使用以下选项进行初始化:

properties.setProperty("auto.offset.reset", "earliest")
kafkaConsumer = new FlinkKafkaConsumer(topic, deserializer, properties)
kafkaConsumer.setStartFromGroupOffsets()
kafkaConsumer.setCommitOffsetsOnCheckpoints(true)

在集群上启用了检查点。

我想要实现的是保证将所有过滤后的数据保存到数据库中,即使数据库关闭了,比如说 6 小时,或者在保存到数据库时出现编程错误并且作业需要更新、重新部署和重新启动。

要发生这种情况,Kafka 偏移量的任何检查点都应该意味着

  1. 从 Kafka 读取的数据处于 Flink 算子状态,等待过滤/传递到接收器,并将作为 Flink 算子检查点的一部分进行检查点,或
  2. 从 Kafka 读取的数据已经提交到数据库中。

在查看 JdbcSink 的实现时,我发现它并没有真正保持任何将被检查点/恢复的内部状态 - 相反,它的检查点是对数据库的写出。现在,如果此写入在检查点期间失败,并且 Kafka 偏移量确实被保存,我将处于“丢失”数据的情况 - 来自 Kafka 的后续读取将从已提交的偏移量恢复,并且当 db写入失败现在不再从 Kafka 读取,也不在数据库中。

那么有没有办法在完整的管道(Kafka -> Flink -> DB)无法执行时停止推进 Kafka 偏移量 - 或者这里的解决方案(在 1.13 之前的世界中)是创建我自己的GenericJdbcSinkFunction 会保持一些 ValueState 直到数据库写入成功?

1 个答案:

答案 0 :(得分:0)

我可以看到 3 个选项:

  1. 在您的 Flink 版本中试用 JDBC 1.13 连接器。它很有可能会奏效。
  2. 如果这不能立即生效,请检查您是否可以将其反向移植到 1.11。不应该有太多变化。
  3. 编写您自己的两阶段提交接收器,通过扩展 TwoPhaseCommitSinkFunction 或使用 SinkFunctionCheckpointedFunction 实现您自己的 CheckpointListener。基本上,您在成功检查点后创建一个新事务并使用 notifyCheckpointCompleted 提交它。