spark从kafka读取并发问题
某些spark分区已经处理完数据,另一些分区还在处理数据,从而导致这个批次的作业消耗时间变长,甚至导致spark作业无法及时消费kafka中的数据。
解决办法:
1)修改kafkaRDD类的getPartition方法:
就是通过设置 topic.partition.subconcurrency 参数,如果这个参数等于1,整个函数的执行效果和之前一样。但是如果这个参数大于1,则之前一个 Kafka 分区由一个 Spark 分区消费的数据变成由 topic.partition.subconcurrency 个 Spark 分区去消费,每个 Spark 分区消费的数据量相等。这个无疑会加快 Kafka 数据的消费,但是这种方法的问题也很明显:
如果数据的顺序很重要,这种方法会存在乱序的问题。
Spark 设计的 KafkaRDD 目的是让 Kafka Partition 和 Spark RDD Partition 一一对应,这样可以保证同一个分区里面的数据顺序,但是这种方法实现变成了 Kafka Partition 和 Spark RDD Partition 一对多的关系,无疑破坏了官方的原有设计。
2)通过 repartition 或 coalease 对数据进行重分区:
优点:对同一类型的数据,先后顺序是不会乱的,因为同一类型的数据,经过重分区还是会分发到同一分区中。
总结:上述两种方法均无法解决kafka端数据倾斜导致的数据处理过慢的问题(消费时间过长)。针对这种情况,我们需要考虑kafka分区设置是否合理?
如果不是kafka分区设置不合理,而是本来kafka分区数量就很大,我们可以考虑增加kafka分区或调节spark资源来解决。建议最好别使用多线程来处理同一个kakfa分区的数据。(因每个Consumer都需要一个TCP链接,会造成大量的系统性能损耗)