刚开始使用Spring Kafka(2.1.4.RELEASE)和Kafka(1.0.0)但是当我添加了事务时,处理速度大大降低了。
代码:
spring.kafka.consumer.max-poll-records=10
spring.kafka.consumer.specific.avro.reader=true
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.group-id=${application.name}
spring.kafka.consumer.properties.isolation.level=read_committed
spring.kafka.consumer.key-deserializer=io.confluent.kafka.serializers.KafkaAvroDeserializer
spring.kafka.consumer.value-deserializer=io.confluent.kafka.serializers.KafkaAvroDeserializer
在Java中我添加了:
@Bean
ProducerFactory<Object, Object> producerFactory(KafkaProperties properties) {
DefaultKafkaProducerFactory<Object, Object> factory = new DefaultKafkaProducerFactory<>(properties.buildProducerProperties());
factory.setTransactionIdPrefix(properties.getProducer().getTransactionIdPrefix());
return factory;
}
@Bean
KafkaTemplate<Object, Object> kafkaTemplate(ProducerFactory<Object, Object> factory) {
return new KafkaTemplate<>(factory, true);
}
@Bean("kafkaListenerContainerFactory")
ConcurrentKafkaListenerContainerFactory<Object, Object> listenerContainerFactory(Environment env, ConsumerFactory<Object, Object> consumerFactory, KafkaTransactionManager<Object, Object> transactionManager) {
ConcurrentKafkaListenerContainerFactory<Object, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setAutoStartup(true);
factory.setConcurrency(1);
factory.setConsumerFactory(consumerFactory);
factory.getContainerProperties().setTransactionManager(transactionManager);
factory.getContainerProperties().setGroupId(env.getRequiredProperty("spring.kafka.consumer.group-id"));
return factory;
}
当我删除setTransactionManager(transactionManager)
语句时,速度增加了很多。有什么我做错了吗?
答案 0 :(得分:2)
Kafka交易相当昂贵 - 特别是如果您提交每次发送。
请参阅Transactions in Apache Kafka。
向下滚动到&#34;交易如何执行,以及如何调整它们&#34;。
正如我们所看到的,开销与作为事务一部分写入的消息数量无关。因此,拥有更高吞吐量的关键是每个事务包含更多的消息。
使用Spring for Apache Kafka,您可以使用executeInTransaction
方法在同一事务中执行多个发送。或者将Spring事务管理与KafkaTransactionManager
一起使用,并在@Transactional
方法中执行多个发送。
修改强>
我没有注意到监听器容器;我假设您正在使用消息,执行一些转换并发送到另一个主题。因此,在这种情况下,您无法在交易中发送多条消息&#34;因为容器管理事务,默认情况下,在每次交付后提交。
增加并发性不会影响事务语义;在您的情况下,(并发10),分区分布在10个线程中。每个线程都运行一个单独的事务。
您可以通过在容器工厂中将batchListener
设置为true
来进一步加快速度。
在这种情况下,@KafkaListener
获得List<ConsumerRecord>
(如果您使用转化,则为List<Foo>
);您可以遍历列表并处理每个记录并使用模板发送它(不要使用executeInTransaction
,因为已经存在由容器线程启动的事务)。然后,当批处理完成时,容器将提交事务。
您可以使用kafka max.poll.records
使用者属性控制批量大小。