我遇到了将键的流从接收器子任务写入输出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将是一个很好的解决方案。但是,如果以后再增加并行性,我认为它不会遵循原始的key-> partition映射,因为它使用此方案选择输出分区。
这里是否可以使用一种技术来满足这些约束?可能是对kafka生产者的设置进行了调整,是对密钥流进行分区的另一种方法还是其他?
答案 0 :(得分:1)
您假设Flink使用的分区逻辑与Kafka使用的分区逻辑相同。给定4个键A,B,C和D,Flink很有可能将A和B发送到一个接收器实例,而C和D将发送到另一个接收器实例(这是我所怀疑的情况)。然后,Kafka可能正在使用一种不同的分区逻辑,该逻辑将A和C发送到一个分区,而B和D写入另一个分区。
Flink似乎不想公开给定密钥的密钥组,但是如果接收器的并行性与Kafka分区的数量相同,那么您应该能够使用接收器实例的task_id在自定义Kafka分区逻辑中。这有点蛮力,但它应该做您想做的事。
我想一想,您还可以为Flink编写一个自定义分区程序,该逻辑使用与Kafka主题的自定义分区程序相同的逻辑。这样就可以扩展到更多的接收器实例。