Partition Assignment Strategy
이번에는 consumer 가 partition을 할당하는 방법에 대해 알아본다. consumer가 partition을 할당하는 방법은 Range, RoundRobin, Sticky, CooperativeSticky, Custom 다섯가지가 있다. Consumer의 partition.assignment.strategy
파라미터로 할당 방식을 조정할 수 있다.
- org.apache.kafka.clients.consumer.RangeAssignor
- Topic별로 작동하는 Default Assignor
- org.apache.kafka.clients.consumer.RoundRobinAssignor
- Round Robin 방식으로 Consumer에게 Partition을 할당
- org.apache.kafka.clients.consumer.StickyAssignor
- 최대한 많은 기존 Partition 할당을 유지하면서 최대균형을 이루는 할당을 보장
- org.apache.kafka.clients.consumer.CooperativeStickyAssignor
- 동일한 StickyAssignor 논리를 따르지만 협력적인 Rebalance을 허용
- org.apache.kafka.clients.consumer.ConsumerPartitionAssignor인터페이스를
- 구현하면 사용자 지정 할당 전략을 사용할 수 있음
Range Assignor
Range Assignor는 partition을 consumer에 순서대로 할당해 주는 방법이다. 0번은 0번끼리, 1번은 1번끼리 매핑이 된다.
partition 개수보다 consumer 개수가 많으면 놀고 있는 consumer가 생긴다. 동일한 Key를 가지고 있는 메시지들에 대한 Topic들간에 “co-partitioning” 하기 유리하다.
Round Robin Assignor
Round Robin Assignor Round Robin방식으로 Partition들과 Consumer들을 분배하여 할당한다. partition이 0번 consumer에 할당되고, 다음에는 1번 consumer에, 다시 다음에는 0번 consume에 할당된다.
Reassign(재할당)이 된다면 Consumer가 동일한 Partition을 유지한다고 보장하지 않는다. 지금 Consumer 0 이 Topic0의 Partition0 에 할당되어 있지만, 재할당이 발생하면 Topic0의 Partition0 이 다른 Consumer에게 할당될 수 있다는 것이다.
Consumer간 Subscribe 해오는 Topic이 다른 경우, 할당 불균형이 발생할 가능성이 있다. C0은 T0만, C1는 T0과 T1만, C2은 T0, T1, T2를 Subscribe 한다고 가정하면 consumer2에게 많은 작업량이 간다. 이를 보완한 것이 StickyAssignor 할당 방식이다.
StickyAssignor
StickyAssignor은 아래 조건을 이용해 가능한한 균형적으로 할당을 보장한다.
- Consumer 들에게 할당된 topic partition의 개수는 최대 1만큼 다름
- Consumer A가 consumer B에 비해 2개 이상 더 적은 topic partition 이 할당된 경우, A에 할당된 topic의 나머지 partition들은 B에 할당될 수 없음
- 재할당이 발생했을 때, 기존 할당을 최대한 많이 보존하여 유지함
만약에 Consumer 1 이 죽으면 Round Robin Assignor 모든 것을 다시 할당한다. 하지만 StickyAssignor는 consumer 1을 제외한 연결은 유지하고 나머지를 다시 할당한다.
이번에는 C0은 T0만, C1는 T0과 T1만, C2은 T0, T1, T2를 Subscribe 한다고 가정하자. Roundrobin 방식에서는 consumer2에게 많은 작업량이 갔었다. 하지만 sticky 방법은 Consumer 들에게 할당된 topic partition의 개수는 최대 1만큼 다르기 때문에 균형적으로 할당이 되는 것을 볼 수 있다.
이 상황에서 consumer 0이 죽으면 StickyAssignor는 원래 것을 남겨두고 T0의 partition을 consumer 2에게 주면 각 consumer 들이 받는 partition의 개수가 2개가 차이나기 때문에 consumer 1에게 할당을 해주면서 균형적인 분배를 할 수 있다.
Cooperative Sticky Assignor
Consumer Rebalancing Process
Cooperative Sticky Assignor을 공부하기 전에 어떻게 consumer rebalancing이 일어나는지 먼저 살펴보자.
- consumer 들이 broker (group coordinator) 에게 joingroup 요청을 보냄
- group coordinator는 각각의 consumer 들에게 joingroup 요청에 대한 응답을 보냄 (group leader는 consumer 들의 순서 정보를 수신)
- 각 consumer들은 broker에게 syncgroup 요청을 보냄 (group leader는 partition 할당을 계산해서 group coordinator에게 전송)
- group coordinator는 syncgroup 요청에 응답해서 각 partition에게 할당을 보냄
Eager Rebalancing Protocol
Eager rebalancing 방법은 원래 소유하고 있던 모든 partition들을 취소한다. 말 그대로 consumer 들이 더이상 consume 할 수 없는 상태가 되는 것이다. 즉, 모든 partition의 연결이 끊어진 시점 부터 다시 새로운 partition이 할당되는 시점까지 아무것도 할 수 없다.
다시 joingroup 요청을 보내면 과거에 배정 되었는 partition에 상관없이 새로운 partition이 할당된다. 그러면 변하지 않은 partition은 계속 연결되어 있게 하고, 새롭게 할당될 patition만 새로 할당하면 더 효율적일 것이다. 그래서 나온 방식이 Incremental Cooperative Rebalancing Protocol이다.
Incremental Cooperative Rebalancing Protocol
Consumer A, B가 Consume하고 있는 상태에서 처리량을 늘이기 위해서 Consumer C를 추가하는 경우를 가정하자. Consumer A에 할당된 Partition중 하나만 Consumer C로 이동하는 것이 가장 이상적인 상황이다. Consumer A도 떼어내는 것 하나 빼고는 계속 consuming을 하는 것이 이상적이다. 전체 재조정 동안 모두 정지 상태로 있는 대신, Consumer A만 하나의 Partition을 취소하는 동안만 가동 중지하는 것이다.
하지만 consumer는 자신의 partition 중에서 어떤 것이 다른 곳으로 재할당 되어야 하는지 알지 못한다. 왜냐하면 joingroup 요청만 보냈지 어떤 것을 revoke 할것이라는 요청을 보낸것이 아니기 때문이다. 정답부터 말하면 rebalancing을 두번을 줘야 한다. 이게 바로 Cooperative Sticky Assignor 가 하는 일이다.
Cooperative Sticky Assignor
Cooperative Sticky Assignor는 두번의 rebalancing을 진행한다. 이전의 assignor 들은 joingroup 요청을 날리는 순간 각 consumer 에 할당되어 있는 모든 partition들을 revoke 시켜버렸다. 하지만 Cooperative Sticky Assignor joingroup 요청을 보내도 소유한 모든 partition들은 보유하고, 그 정보를 group coordinator에게 같이 보낸다. 그리고 응답을 받고, syncgroup 요청을 하면, 이때 어떤 partition을 떼어내라고 하는 응답을 받게 된다. broker가 계산해서 어떤 partition을 떼어내면 좋겠다고 말해주는 것이다.
2번째 rebalancing에서는 Partition을 취소한 구성원은 그룹에 ReJoin 하여 취소된 Partition을 할당할 수 있도록 두 번째 재조정을 트리거한다. 그러면 취소된 partition에 대한 재할당이 일어나 consumer C에 3번 partition이 할당되는 형태이다. 즉, 원래 할당되어 있던 partition들은 계속해서 consume이 일어날 수 있고 3번 partition에 대해서만 잠깐 consume이 중지되어 더 좋은 효율성을 가진다.
(참고) Incremental Cooperative Rebalancing 프로토콜은 Apache Kafka 2.5에서 추가되었다.