我在将键控流从接收器子任务写入输出 kafka 主题时遇到问题。
作业的形式是:源 -> 过滤器 -> keyby(id( ->平面图 -> 接收器
异常来自 kafka 生产者,并导致检查点超时:
-
FlinkKafkaException: Failed to send data to Kafka: Failed to allocate memory within the configured max blocking time
-
FlinkKafkaException: Failed to send data to Kafka: Expiring 16 record(s) for mytopic-11:120000 ms has passed since batch creation
作业在出现上述异常时会进入崩溃循环,偶尔会暂时恢复,然后再次崩溃循环。我相信这里的问题是我正在使用键来确定输出分区,这导致 P 接收器子任务将每个扇出写入 N 个输出分区。理想情况下,每个子任务只会写入单个分区。
作业具有以下约束/属性:
1:一旦一个键被写入输出 Kafka 主题分区,它以后需要始终写入到同一个 Kafka 分区
2:接收器子任务并行度最初等于输出分区数
3:我应该能够在不违反#1的情况下增加将来的并行度
4:我永远不会在输出kafka主题中添加新分区
如果parallelism == partitions
,那么我相信FlinkFixedPartitioner将是一个很好的解决方案。但是,如果我后来增加并行性,我认为它不会尊重原始的键>分区映射,因为它使用此方案选择输出分区。
有没有一种技术可以在这里使用来满足这些约束?可能是对 kafka 制作者的设置的调整、对键控流进行分区的另一种方法,还是其他方法?
你假设 Flink 使用的分区逻辑与 Kafka 使用的分区逻辑相同。完全有可能(这就是我怀疑正在发生的事情(给定 4 个键 A、B、C 和 D,Flink 会将 A 和 B 发送到一个接收器实例,而 C 和 D 将发送到另一个接收器实例。 然后,Kafka 可能使用不同的分区逻辑,将 A 和 C 发送到一个分区,而将 B 和 D 写入另一个分区。
Flink 似乎不想公开给定键的键组,但如果接收器的并行度与 Kafka 分区的数量相同,那么您应该能够在自定义 Kafka 分区逻辑中使用接收器实例的task_id。 这有点蛮力,但它应该做你想做的事情。
当我进一步考虑时,您还可以为 Flink 编写一个自定义分区程序,该分区程序使用与 Kafka 主题的自定义分区程序相同的逻辑。 这将处理横向扩展到接收器的更多实例。