728x90
반응형
SMALL

Partition을 Consumer에게 할당하는 전략들

  • RangeAssignor : Topic 별로 작동하는 Default Assignor
  • RoundRobinAssignor : Round Robin 방식으로 Consumer에게 Partition 할당
  • StickyAssignor : 최대한 많은 기존 Partition 할당을 유지하면서 최대 균형을 이루는 할당을 보장
  • CooperativeStickyAssignor : 동일한 StickyAssignor 논리를 따르지만 협력적인 Rebalance를 허용
  • ConsumerPartitionAssignor : 인터페이스를 구현하면 사용자 지정 할당 전략을 사용할 수 있다.

 

RangeAssignor

  • partition.assignment.strategy 파라미터의 기본 Assignor이다.
  • 동일한 Key를 가지고 있는 메시지들에 대한 Topic들 간에 "co-partitioning"하기 유리

  • 0번은 0번으로, 1번은 1번으로 간다고 생각하면 된다.

 

RoundRobinAssignor

  • Range 방식보다는 효율적으로 분배하여 할당, 왜냐하면 위 기본 Assignor는 남는 Consumer가 있을 수가 있다.
  • Round Robin 방식으로 Partition들과 Consumer들을 분배하여 할당
  • Reassign(재할당) 후 Consumer가 동일한 Partition을 유지한다고 보장하지 않는다. 예를 들어, Consumer 0이 지금 Topic 0의 Partition 0에 할당되어 있다고 가정할 때, 재할당이 발생하면 Topic 0의 Partition 0이 다른 Consumer에게 할당될 수 있다.

 

근데 이 방식은 할당 불균형이 발생할 가능성이 존재한다. 

  • Consumer간 Subscribe 해오는 Topic이 다른 경우, 할당 불균형이 발생할 가능성이 있다.
  • 3개의 Consumer C0, C1, C2와 3개의 Topic T0, T1, T2가 있다.
  • T0은 Partition 1개, T1은 Partition 2개, T2는 Partition 3개가 있다.
  • C0은 T0만, C1은 T0과 T1만, C2는 T0, T1, T2를 Subscribe 한다고 가정하면 위 그림과 같은 현상이 일어난다.
  • 라운드 로빈 방식으로 순서대로 Consumer에 Partition이 할당되긴 하지만 T2를 Subscribe하는 Consumer는 C2밖에 없기 때문에 저쪽에 쏠리게 된다.

 

StickyAssignor

  • 가능한 한 균형적으로 할당을 보장한다.
  • 특정 ConsumerA가 다른 ConsumerB에 비해 2개 이상 더 적은 Topic Partition이 할당된 경우, A에 할당된 Topic의 나머지 Partition들은 B에 할당될 수 없다.
  • 재할당이 발생했을 때, 기존 할당을 최대한 많이 보존하여 유지. 따라서, Rebalancing 오버헤드를 줄임

  • Round Robin 방식과 비슷하지만 다른 방식으로 동작하는데, 
  • 3개의 Consumer C0, C1, C2와 4개의 Topic T0, T1, T2, T3가 있다고 하자.
  • T0, T1, T2, T3는 모두 Partition 2개가 있다고 하자.
  • C0, C1, C2 모두 T0, T1, T2, T3를 Subscribe 한다고 하자.
  • 위 그림을 보면 얼핏 라운드 로빈 방식과 다를게 없어 보인다.

 

만약, 여기서 C1이 제거되어 재할당하면 어떻게 될까?

  • 라운드 로빈의 경우 전체를 다시 재할당한다. (왼쪽)
  • Sticky Assignor의 경우, 기존에 되어 있던 할당들은 유지하고 C1이 가지고 있던 Partition만 재할당한다. (오른쪽)

 

Round Robin에서 발생할 수 있었던 할당 불균형이 발생할 가능성을 줄인다는 건 어떤걸까?

  • Round Robin 방식에서 설명했던 할당 불균형이 발생했던 시나리오는 다음과 같다.
  • 3개의 Consumer C0, C1, C2와 3개의 Topic T0, T1, T2가 있다.
  • T0은 Partition 1개, T1은 Partition 2개, T2는 Partition 3개가 있다.
  • C0은 T0만, C1은 T0, T1만, C2는 T0, T1, T2를 Subscribe한다.
  • 따라서, C2만 많은 Partition이 몰리게 된다.

근데 이 문제를 Sticky는 이렇게 해결한다.

  • C2가 T1-P1, T2-P0, T2-P1, T2-P2 4개를 할당하고 있으니, T1을 할당할 수 있는 C1, C2 중에서 C2말고 C1에게 T1-P1을 할당시키는 것이다. 
  • 기본적으로 라운드 로빈으로 할당을 하는데, 그렇게 할당하고 나서 보니 특정 Consumer가 너무 많은 할당을 받으면 부담을 덜 수 있게 할당 받을 수 있는 Consumer를 찾아서 불균형을 해소한다.

 

CooperativeStickyAssignor

이 내용을 설명하기 앞서, 시간 흐름에 따른 Consumer Rebalancing 과정을 먼저 알아보기로 한다.

  • 1. Consumer들이 JoinGroup 요청을 Group Coordinator에 보내면서 리밸런싱이 시작된다.
  • 2. JoinGroup의 응답이 Consumer들에 전송된다. (Group Leader는 Consumer들 정보를 수신)
  • 3. 모든 구성원은 Broker에 SyncGroup 요청을 보내야 한다. (Group Leader는 각 Consumer의 Partition 할당을 계산해서 Group Coordinator에게 전송)
  • 4. Broker는 SyncGroup 응답에서 각 Consumer 별 Partition 할당을 보낸다.

Eager Rebalancing 프로토콜

지금까지 사용됐던 방식이고, 이 프로토콜은 최대한 단순하게 유지하기 위해 만들어졌다.

  • 각 구성원은 JoinGroup 요청을 보내고 재조정에 참여하기 전에 소유한 모든 Partition을 취소해야 한다. 재조정을 하기 위해 취소하고 다시 할당을 받는건데, 이때 원래 소유하던 Partition을 다시 할당받을 수도 있고 아닐수도 있다.
  • 안전면에서는 좋지만, 이 경우에 재조정 기간동안 작업을 할 수 없다는 단점이 있다. 

그런데, 생각해보면 재조정 시 Revoke할 Partition만 Revoke하면 되지 않을까? 

이 문제를 해결하기 위해 나온 것이 Cooperative Rebalancing Protocol이다.

 

이상적인 Consumer Rebalancing 프로토콜

  • Consumer A, B가 Consume 하고 있는 상태에서 처리량을 높이기 위해 Consumer C를 추가한다고 가정해보자.
  • Consumer A에 할당된 Partition 중 하나만 Consumer C로 이동하는 것이 가장 이상적일 것이다.
  • 전체 재조정동안 모두 정지 상태로 있는 대신, Consumer A의 하나의 Partition을 취소하는 동안만 해당 Partition으로 데이터 처리하는 작업만 가동 중지하는 것이다.

  • 보면, Consumer A의 3번만 떼어내서, Consumer C로 이동시키는 것이다.
  • 3번을 revoke하면서 재조정이 필요해지고, 모든 Consumer 들이 다시 Group Coordinator에 JoinGroup 요청을 보내고 응답을 받고 ... 이 과정을 하면서 3번만 그 시간동안 중지하고 Consumer C에 붙은 후부터 다시 3번도 동작하도록 말이다.

그런데 이 과정에 문제가 하나 있는데, 바로 Consumer는 자신의 Partition 중 어느것이 다른곳으로 재할당되어야 하는지 알지 못한다는 것이다. 이 부분은 어떻게 해결할 수 있을까?

CooperativeStickyAssignor는 Rebalancing을 2회에 걸쳐 수행한다.

  • 첫번째 rebalance 과정에서는, 모든 Consumer들이 JoinGroup 요청을 보내면서 시작하지만, 소유한 모든 Partition을 보유하고 그 정보를 Group Coordinator에게 보낸다. 즉, 계속 처리할 수 있는 상태로 진행한다는 것이다.
  • 그럼 Group Coordinator가 JoinGroup 요청을 받고 응답을 준 다음에 SyncGroup 요청을 받고 SyncGroup 요청에 대한 응답을 보낼 때, 어떤 Partition을 떼어내야 할 지 해당 Consumer에게 알려준다!
  • 여기까지가 1st rebalance 과정이다.
  • 그 다음 어떤 걸 떼어내야 하는지 알게됐으니 해당 Partition을 떼어내고 다시 JoinGroup 요청을 보낸다. 그리고 쭉 과정이 진행되면서 3번 Partition이 Consumer C로 이전되는 것이다.
  • 자 이 과정에서 Consumer A는 3번만 중간에 잠깐 떼어내고 나머지들은 작업을 계속 진행할 수 있었다. 이렇게 나이스한 Rebalancing 작업을 수행할 수 있게 해주는 것이 CooperativeStickyAssignor이다.

 

정리를 하자면

  • CooperativeStickyAssignor는 2회에 걸쳐 Rebalancing을 진행한다.
  • 빈번하게 Rebalancing 되는 상황이거나, 스케일 인/아웃으로 인한 다운타임이 우려가 된다면, CooperativeStickyAssignor를 사용하는 것을 권장한다.

 

728x90
반응형
LIST

'Apache Kafka' 카테고리의 다른 글

p13. Exactly Once Semantics(EOS)  (0) 2025.03.23
p12. Kafka Log File  (0) 2025.03.16
p10. Consumer Rebalance  (0) 2025.03.16
p9. Replica Recovery  (0) 2025.03.16
p8. Replica Failure  (0) 2025.03.15

+ Recent posts