背景:
kafka在2.4.0版本合入的一个KIP-480,它的核心逻辑就是当存在无key的序列消息时,我们消息发送的分区优先保持粘连,如果当前分区下的batch已经满了或者 linger.ms延迟时间已到开始发送,就会重新启动一个新的分区。这种策略使得每个batch更大,能够显著地降低给消息指定分区过程中的延时和请求数。
冲突:
sticky策略在kafka2.4版本以后在java和c++客户端的default partitioner(c++中为consistent random partitioner)中是默认使用的,对于无key的消息会使用sticky partitioner的逻辑,但针对有key的消息,kafka还是会使用default partitioner。这使得我们无法让有key的消息也使用sticky partitioner,在kafka官方文档中也没有示例。
解决方案:
1. java kafka客户端
首先想要使用带有sticky策略的kafka clients就需要在pom.xml引入2.6及以上版本的依赖。然后通过kafka producer的config设定partitioner,代码如下所示。
Properties props = new Properties();
props.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, UniformStickyPartitioner.class);
通过这段代码将partitioner设定为UniformStickyPartitioner,就可以将所有消息都通过sticky策略发送了,无论消息是否有key。
2. c++ librdkafka客户端
不幸的是在librdkafka中的kafka client和java版本完全不同,也没有UniformStickyPartitioner而使用一个rd_kafka_msg_sticky_partition的方法来实现sticky策略,所以如果想要仅使用sticky策略就需要更改librdkafka的代码,比如说增加一个参数,然后更改consistent random partitioner的部分逻辑,将有key的消息也通过调用rd_kafka_msg_sticky_partition来选择分区。