학습 자료
Rebalance
- 토픽 내 파티션을 컨수머에게 재할당 하는 것을 ‘리밸런싱’ 이라고 한다.
- 리밸런싱은 기본적으로 컨수머 그룹의 가용성(availability)과 규모 가변성(scalability)을 제공하지만, 전략에 따라 오히려 가용성과 규모 가용성을 저해하기도 한다.
- 리밸런싱은 아래 상황에서 발생한다.
- 토픽 내 파티션을 새로 추가할 때.
- 컨수머 그룹 내에 신규 컨수머를 추가할 때.
- 컨수머 그룹 내에 일부 컨수머가 종료/크래시 되었을 때.
- 리밸런싱 전략은 크게 eager / cooperative 으로 나뉘고 two-phase commit 방식을 쓴다. https://www.confluent.io/blog/cooperative-rebalancing-in-kafka-streams-consumer-ksqldb/
Eager Rebalance
- eager rebalancing 하는 도중에는 컨수머그룹 내 모든 컨수머들이 메세지 읽기를 멈추고 파티션 멤버십도 포기한다. (called 'stop the world' event)
- eager rebalancing 완료되고 나면 컨수머들은 이전에 할당 받았던 파티션과 다른 파티션을 새로 할당받게 된다.
- 컨수머들이 메세지 읽기 작업을 멈췄다가 파티션을 재할당 받기까지 걸리는 시간(다운타임)은 컨수머그룹의 규모가 클수록 길어진다. → 운영에서 안 쓸거 같다.
위 그림은 모든 컨수머들이 컨수머그룹에 탈퇴하고 나서 파티션을 재할당 받는 과정을 나타낸다.
- 컨수머들은 그룹 코디네이터에게
JoinGroup
요청을 보낸다. (컨수머 → 그룹 코디네이터 갈색 화살표) 이 때, 컨수머들 중에 가장 먼저 조인한 컨수머가 리더가 된다. (위 그림에서는C
가 리더가 될 것.)
- 그룹 코디네이터는 컨수머들에게
JoinGroup
요청에 대한 응답을 보내는데, 리더에게는 응답에 컨수머 목록을 포함하여 전달한다. (그룹 코디네이터 → 컨수머 갈색 화살표)
- 리더는 그룹 코디네이터로부터 받은 컨수머 목록을 기반으로 어느 컨수머에게 어느 파티션을 할당할지 결정한다.
- synchronization barrier : 파티션들을 재할당하는 시점에 파티션들은 모두 멤버십이 포기되어 있어야 함을 나타낸다.
- 컨수머들이 그룹 코디네이터에게
SyncGroup
요청을 보낸다. 리더는SyncGroup
요청에 할당 결과를 포함하여 전달한다.(컨수머 → 그룹 코디네이터 노란색 화살표)
- 그룹 코디네이터는 리더로부터 받은 파티션 할당 결과를
SyncGroup
에 대한 응답에 포함하여 보낸다. (그룹 코디네이터 → 컨수머 노란색 화살표)
Cooperative Rebalance
- 3.1 버전 이후로 디폴트로 쓰인다.
- 토픽 내 일부 파티션만 기존 컨수머에서 다른 컨수머에게 재할당한다.
- 다른 컨수머들은 리밸런싱에 방해받지 않고 기존에 할당받은 파티션에서 메세지를 읽는 작업을 유지한다.
- cooperative rebalancing 과정은 아래와 같다.
- 컨수머그룹 내 리더가 다른 컨수머들에게 리밸런싱 한다고 통보한다.
- 리더에게 통보를 받고 나면 다른 컨수머들은 메세지를 읽고 있었던 파티션에 대한 멤버십을 포기한다.
- 컨수머그룹 내 리더는 파티션들을 재할당한다.
위 그림은 컨수머들이 리밸런싱 통보를 받고 나서 컨수머
A
가 멤버십을 갖고 있었던 3번 파티션을 C
에게 재할당하는 과정을 나타낸다.1st rebalance
- 컨수머들은 자기가 어느 파티션을 소유하고 있는지에 대한 정보를 포함하여 그룹 코디네이터에게
JoinGroup
요청을 보낸다.
- 그룹 코디네이터는 컨수머들에게
JoinGroup
에 대한 응답을 보내는데, 리더에게는 컨수머들의 파티션 멤버십 정보를 포함하여 응답을 보낸다.
- 컨수머들은 그룹 코디네이터에게
SyncGroup
요청을 보내는데, 리더는 컨수머A
에게 3번 파티션 멤버십을 회수한다는 정보를 포함하여 요청한다.
- 그룹 코디네이터는
A
에게 3번 파티션을 제외한다는 정보를 포함하여SyncGroup
에 대해 응답한다. - synchronization barrier : 3번 파티션의 멤버십이 포기되어 있어야 함을 나타낸다.
2nd rebalance
- 컨수머들은 자기가 어느 파티션을 소유하고 있는지에 대한 정보를 포함하여 코디네이터에게
JoinGroup
요청을 보낸다 .(A
의 파티션 멤버십 정보에는 3번 파티션이 없을 것.)
- 그룹 코디네이터는
JoinGroup
에 대해 응답한다.
- 컨수머들이
SyncGroup
요청을 보내는데, 리더 컨수머는C
에게 3번 파티션을 할당한다는 정보를 포함하여 요청한다.
- 그룹 코디네이터는
C
에게 3번 파티션이 할당되었다는 정보를 포함하여SyncGroup
에 대해 응답한다.
Partition Assignor
- 리더 컨수머가 어느 파티션을 어느 컨수머에게 할당할지 결정할 때 쓰인다.
- Range, RoundRobin, Sticky 방식은 eager 리밸런싱을 일으킨다.
레인지 (Range)
- 무조건 고정된 파티션 묶음을 특정 컨수머에게 할당한다.
- ex) 어떤 컨수머그룹이 구독하는
a
,b
,c
토픽에 각각 파티션이 3개 있다면 0~1 번 파티션은 무조건 컨수머A
에게, 2번 파티션은 컨수머B
에게 할당.
- 파티션 재할당 계산에 의한 지연시간은 적겠지만 특정 컨수머에게 파티션이 치중될 수 있다.
라운드-로빈 (Round Robin)
- 모든 토픽의 파티션들을 가져다 순차적으로 컨수머에게 돌아가며 할당한다.
- 레인지 전략에 비해 컨수머에게 균등하게 파티션을 할당할 수 있다.
- 컨수머 그룹의 규모가 크다면 재할당 계산 비용이 많이 발생할 수 있다.
스티키 (Sticky)
- 컨수머들에게 최대한 균등하게 파티션을 할당하면서, 재할당 계산 비용을 최대한 줄이는 걸 목표로 한다.
- 처음에 컨수머그룹을 생성할 때 라운드-로빈 방식으로 파티션을 할당하지만, 리밸런싱이 일어나면 기존 컨수머들의 파티션 멤버십에 최대한 변화를 주지 않고 재할당이 일어나도록 한다.
- 하지만 eager 리밸런싱을 일으켜서 컨수머들이 메세지 읽기 작업을 멈추기 때문에 다운타임이 생긴다는 단점이 있다.
코퍼레티브 스티키 (CooperativeSticky)
- Sticky 방식의 단점을 보완한 방식으로, cooperative 리밸런싱을 통해 다운타임을 개선한다.
Static Group Membership
- static group membership 은 리밸런싱이 의도하지 않게 자주 발생하는 것을 개선한다.
- 컨수머가 그룹 코디네이터에게 heartbeat 를 보내지 않으면 그룹 코디네이터는 기본적으로 컨수머가 죽은 것으로 간주하고 리밸런싱을 한다. 죽었다고 간주된 컨수머는 컨수머그룹에서 탈퇴된 후 재가입 했을 때 새로운 멤버 ID 를 발급받으며, 어떤 파티션 어사이너를 쓰는지에 따라 이전에 소유했던 파티션과 다른 파티션을 할당 받을 수 있다.
- 하지만 컨수머에게 static group membership 을 부여하면 (
group.instance.id
를 지정하면) 컨수머의 heartbeat 주기가 잠깐 멈추더라도 (혹은 정말로 죽었다가 살아돌아와도) 그룹 코디네이터는 컨수머를 컨수머그룹에서 탈퇴시키지 않고 리밸런싱도 발생하지 않는다. (리밸런싱이 발생하지 않는다는 건 파티션 재할당이 일어나지 않고 파티션의 멤버십이 해당 컨수머에게 유지된다는 뜻이다.)
- static group membership 을 유지하는 기간은
session.timeout.ms
설정에 의존한다. 즉,session.timeout.ms
내에 컨수머가 heartbeat 를 보내지 않으면 컨수머그룹에서 탈퇴되고 리밸런싱이 일어난다.
- static group membership 은 컨수머가 파티션으로부터 읽은 메세지를 가지고 캐시를 생성하는 데에 시간이 오래걸리거나, k8s 환경에서 rolling out 배포 방식을 사용할 때 유용하다.