sanghyeok An created KAFKA-21279:
------------------------------------

             Summary: Consumer and Streams group leave append failures can lose 
session timers and stall reassignment
                 Key: KAFKA-21279
                 URL: https://issues.apache.org/jira/browse/KAFKA-21279
             Project: Kafka
          Issue Type: Bug
            Reporter: sanghyeok An
            Assignee: sanghyeok An


When a member using {{group.protocol=consumer}} or {{group.protocol=streams}} 
leaves its group, the coordinator cancels the member’s session timer before 
persisting the member removal records.

If the subsequent local append to {{__consumer_offsets}} fails, the 
coordinator’s snapshot rollback restores the member metadata, existing 
assignment, and ownership state. However, session timers are not managed by the 
snapshot mechanism, so the canceled timer is not restored.

As a result, the coordinator retains a member that has already shut down as the 
owner of Consumer partitions or Streams active tasks, but no longer has a 
session timer to expire that member. Even after the append failure is resolved 
and other members continue sending successful heartbeats, the departed member’s 
partitions or tasks may remain unreleased, leaving processing stalled.

The two protocols use different leave handlers, but share the same underlying 
cause: timers are canceled before persistence and are not restored on rollback.

 

*Scenario*
 # Dynamic members A and B belong to the same group, with stable assignments. 
In a Consumer group, A consumes P0 and B consumes P1. In a Streams group, A and 
B belong to different processes: A processes active task {{{}0_0{}}}, and B 
processes active task {{{}0_1{}}}.
 # A shuts down and sends a heartbeat with {{memberEpoch=-1}} using the 
corresponding protocol. A sends no further heartbeats. For Streams, this is an 
ordinary member departure without requesting application-wide shutdown.
 # The coordinator generates A’s removal records and a group epoch update 
record, then calls {{cancelTimers()}} to cancel A’s timers before persisting 
the records.
 # The local append of the batch containing these records fails. The 
coordinator remains ACTIVE without reloading and performs a snapshot rollback.
 # A’s member metadata and existing partition or active task ownership are 
restored, but A’s session timer is not.
 # The cause of the append failure is resolved. B continues sending successful 
heartbeats and processing its existing partitions or tasks, but B’s heartbeats 
refresh only B’s own session timer.
 # A is not removed even after its session timeout has elapsed. Consumption of 
P0 remains stalled in the Consumer group, or processing of task {{0_0}} remains 
stalled in the Streams group.

Even if a subsequent rebalance changes the target assignment to move the 
affected partition or task to B, B may be unable to acquire it while the 
coordinator still retains A’s current ownership.

For Streams, this scenario does not require a stateful topology, standby or 
warm-up replicas, or a custom assignor.

 

*Conditions that can cause the append failure*

One possible path is a reduction of {{max.message.bytes}} for 
{{__consumer_offsets}} between batch creation and append. Both group types use 
the same coordinator runtime persistence path, so this condition applies to 
both.

The coordinator runtime uses the size limit in effect when creating a batch. If 
the limit is subsequently reduced and the actual size of the batch containing 
A’s leave records exceeds the new limit, the log append can fail with 
{{{}RecordTooLargeException{}}}.

In this failure path, rolling back the batch does not necessarily reload the 
coordinator. Restoring the size limit allows subsequent writes to succeed, but 
does not restore A’s canceled session timer.

 

*Impact*

In Consumer groups, consumption of the departed member’s partitions may remain 
stalled. In Streams groups, input processing for the departed member’s active 
tasks may remain stalled. Other members can continue processing the partitions 
or tasks they already own, so the issue does not necessarily stop processing 
across the entire group.

Reloading the coordinator can register the members’ session timers again. This 
is therefore not permanent log corruption, but restoring successful writes and 
waiting for the session timeout are insufficient to guarantee that the affected 
partitions or tasks will be released.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to