0

I have a Kafka topic gbtopic with 12 partitions and a consumer group gbconsumers with three consumers C1, C2, C3 subscribing to this topic. When all consumers are started, each consumer is allocated with 4 partitions. Then I stopped consumer C3. Now partitions are rebalanced with 6 partitions each to C1 and C2. Now I started consumer C3, and partitions are rebalanced and allocated to C1, C2, C3. My expectation is to get the same set of partitions back with C1, C2, C3 as was assigned before stopping C3.

I am using StickyAssignor for partition.assignment.strategy. I am performing the operations in the following order:

Start C1
Start C2
Start C3
Stop C3
Restart C3
Following is my client program:
public class ConsumerApp {
    public static void main(String[] args) {
        Scanner scanIn = new Scanner(System.in);
        System.out.print("Enter Consumer Name :: ");
        String consumerId = scanIn.nextLine().trim();
        scanIn.close();

        Properties props = new Properties();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        props.put(ConsumerConfig.GROUP_ID_CONFIG, "gbconsumers");
        props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");
        props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "30000");
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, StickyAssignor.class.getName());
        props.put(ConsumerConfig.CLIENT_ID_CONFIG, consumerId);

        KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<>(props);
        ConsumerRebalanceListener listener = new ConsumerRebalanceListener() {
            @Override
            public void onPartitionsRevoked(Collection<TopicPartition> collection) {
                System.out.println("-------------------------------------------------------------------------------------");
                System.out.println(consumerId + " :: onPartitionsRevoked :: " + collection);
            }

            @Override
            public void onPartitionsAssigned(Collection<TopicPartition> collection) {
                System.out.println(consumerId + " :: onPartitionsAssigned :: " + collection + "\n");
            }
        };
        kafkaConsumer.subscribe(Collections.singletonList("gbtopic"), listener);
        while (true) {
            ConsumerRecords<String, String> records = kafkaConsumer.poll((100));
            for (ConsumerRecord<String, String> record : records) {
                performSomeOperation(record);
            }
        }
    }

    private static void performSomeOperation(ConsumerRecord<String, String> record) {
        // operations
    }
}

Output when all three consumers running, before stopping C3


    C1 :: onPartitionsAssigned :: [gbtopic-10, gbtopic-11, gbtopic-8, gbtopic-9]
    C2 :: onPartitionsAssigned :: [gbtopic-2, gbtopic-3, gbtopic-4, gbtopic-5]
    C3 :: onPartitionsAssigned :: [gbtopic-0, gbtopic-1, gbtopic-6, gbtopic-7]

Output after stopping and starting C3:


    C1 :: onPartitionsAssigned :: [gbtopic-0, gbtopic-10, gbtopic-11, gbtopic-6]
    C2 :: onPartitionsAssigned :: [gbtopic-4, gbtopic-5, gbtopic-1, gbtopic-7]
    C3 :: onPartitionsAssigned :: [gbtopic-2, gbtopic-3, gbtopic-8, gbtopic-9]

I expect the partitions assigned to each consumer after stop/restart C3 to be the same as they were before stop/restart. Am I missing any property or is there any other way to achieve this?

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
GirishB
  • 134
  • 7
  • 4
    The `StickyAssignor` does not guarantee that the partitions will be assigned to the same consumers each time. It actually tries to preserve as many assignments as possible when a rebalance happens. *C1* and *C2* still have two of their original partitions which is perfectly reasonable. The second rebalance will try to preserve as many as possible out of 6 partitions. In your example, it took two partitions from before the first rebalance to hand off to *C3*. – Matt Jun 21 '19 at 09:10
  • https://kafka.apache.org/10/javadoc/org/apache/kafka/clients/consumer/StickyAssignor.html--Go through this once for ref –  Jun 21 '19 at 09:16
  • 1
    You can assign the partitions manually if you really must and can go without the automatic rebalancing features. See here for a comparison: https://stackoverflow.com/questions/53938125/kafkaconsumer-java-api-subscribe-vs-assign – Matt Jun 21 '19 at 09:28

0 Answers0