서론
Kafka Consumer는 여러 가지 이벤트를 통해 리밸런싱이 발생한다.
- Consumer ↔ GroupCoordinator 간
session.timeout.ms
내에Heartbeat
가 수신되지 않은 경우 - Consumer가 Consumer Group을 나가거나 들어오는 경우
- Consumer Group이 구독하는 토픽의 파티션이 추가되는 경우 등
Consumer는 리밸런싱이 시작되면 완료되기 전까지 데이터를 처리하지 못한다. 이로 인해 데이터 처리가 일시 중단되며 지연이 발생한다.
또한, 리밸런싱 과정에서 파티션을 Revoke/Assign
하는 과정에서 네트워크 부하 등으로 인한 클러스터 성능 저하가 발생한다.
Kafka 2.3.0부터는 이러한 리밸런싱의 단점을 보완하기 위해 Static Membership
이라는 메커니즘이 도입되었다.
Consumer Group Membership Strategy
Kafka의 Consumer Group Membership에는 다음 2가지 방식이 있다.
Dynamic Membership
Static Membership
Static Membership
은 리밸런싱 횟수를 줄이고자 KIP-345에서 제안되어 Kafka 2.3.0에 도입됐다.
Dynamic Membership
Consumer Group에 속한 각 Consumer는 member.id
라는 고유 ID를 부여받는다.
Dynamic Membership
에서는 각 Consumer가 Consumer Group에 참여할 때마다 새로운 member.id
가 발급된다.
따라서, GroupCoordinator는 Consumer Group에 새로 참여하는 모든 Consumer를 새로운 Consumer로 인식하게 된다.
예를 들어, Consumer Group에 속한 특정 Consumer에게 잠깐의 순단이 발생했다고 가정해보자.
Consumer는 고유한 멤버 ID를 갖고 있으며, con-1, con-2, con-3의 ID를 가진 상태라고 하자.
con-1이 Consumer Group을 탈퇴하면 LeaveGroup
에 따른 리밸런싱이 발생한다.
이 때, con-1이 처리하던 토픽 파티션은 revoke
되고, 다른 Consumer에게 assign
된다.
Consumer가 다시 Consumer Group에 들어오기 위해 요청한다.
GroupCoordinator는 이를 새로운 Consumer로 인식해 con-A라는 새로운 member.id
를 발급한다.
con-A는 Consumer Group에 들어오고 새로운 토픽 파티션을 할당받는다.
잠깐의 순단으로 인해서 2번의 리밸런싱이 발생했다.
그림으로는 간단해보이지만, Consumer A → B로 토픽 파티션을 리밸런싱하는 작업은 많은 양의 데이터 전송이 필요하다.
Static Membership
Static Membership
에서는 GroupCoordinator가 특정 Consumer가 기존에 Consumer Group에 속해 있었던 Consumer임을 인식하도록 설계된다.
이를 위해 각 Consumer는 고유한 group.instance.id
를 설정해줘야 하며, 이 설정을 통해 Static Membership
을 사용할 수 있다.
# Consumer 1
props.put("group.instance.id", "con-1");
Dynamic Membership
에서 사용한 예시로 Static Membership
을 적용했을 땐 어떻게 동작하는지 확인해보자.
con-1이 Consumer Group을 탈퇴한다.
이 때, con-1은 GroupCoordinator에게 Consumer Group 탈퇴를 알리지 않으므로 리밸런싱이 발생하지 않는다.
리밸런싱이 발생하지 않기 때문에 con-1이 처리하고 있던 토픽 파티션은 어떠한 Consumer에게도 할당되지 않은 상태로 남는다.
con-1이 다시 Consumer Group으로 돌아온다.
GroupCoordinator는 con-1이 이미 Consumer Group에 속했던 Consumer임을 인지하므로 리밸런싱이 발생하지 않는다.
con-1은 그대로 다시 자신이 처리하던 토픽 파티션을 할당받아 처리한다.
Static Membership
을 사용하면 Dynamic Membership
을 사용할 때와 달리 리밸런싱이 발생하지 않은 것을 확인할 수 있다.
Static Membership
을 적용하고 리밸런싱을 피함으로써 리밸런싱 시 발생할 수 있는 단점들을 피할 수 있다.
위에 내용을 설명할 때 고려하지 않은 부분이 있다. Consumer가 Consumer Group으로 돌아오지 않을 수도 있다.
할당받지 않은 토픽 파티션은 결국 다른 Consumer가 할당받아 처리해야 한다. 토픽 파티션을 무한히 처리하지 않도록 방치할 수 없기 때문이다.
Static Membership
은 기존 Consumer가 다시 Consumer Group으로 돌아와서 토픽 파티션을 처리하기 까지 대기하는 유예 기간으로 session.timeout.ms
를 사용한다.
session.timeout.ms
내에 기존 Consumer가 돌아오지 않으면 GroupCoordinator는 리밸런싱을 트리거한다.
그리고 처리되지 않던 토픽 파티션을 새로운 Consumer에게 Assign되어 처리된다.
따라서, Static Membership
을 사용시에는 Consumer가 재시작되는 시간을 고려해 적절한 값으로 session.timeout.ms
를 지정해야 한다.
예를 들어, Consumer가 Consumer Group에 다시 들어오기 까지 약 1분이 걸린다면 session.timeout.ms
를 1분보다 큰 값으로 지정해야 불필요한 리밸런싱을 줄일 수 있다.
Reference.
Conduktor: https://learn.conduktor.io/kafka/consumer-incremental-rebalance-and-static-group-membership/
Confluent: https://www.confluent.io/blog/dynamic-vs-static-kafka-consumer-rebalancing/
실전 카프카 개발부터 운영까지
'Kafka > Kafka' 카테고리의 다른 글
Kafka Issue: InvalidRecordException (related Timestamp) (0) | 2024.06.01 |
---|---|
Kafka: Kafka Broker 내부 구조 (0) | 2024.04.28 |