A custom partitioner fits when the hash is wrong for you: isolating a huge customer, or a mapping any language can reproduce, such as order n to partition n modulo the count.
import java.nio.charset.StandardCharsets;
import java.util.Map;
import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
public class OrderIdPartitioner implements Partitioner {
@Override public int partition(String topic, Object key, byte[] keyBytes, Object value,
byte[] valueBytes, Cluster cluster) {
long orderId = Long.parseLong(new String(keyBytes, StandardCharsets.UTF_8));
return (int) (orderId % cluster.partitionCountForTopic(topic));
}
@Override public void configure(Map<String, ?> configs) {}
@Override public void close() {}
}Interceptors and Metrics runs it: orders 7, 8 and 9 land in partitions 1, 2 and 0. librdkafka takes no partitioner class; pass partition=int(key) % 3 to produce(). Either way, never change the partition count afterwards.