Kafka/Kafka

[실전 카프카 개발부터 운영까지 정리] 6장. 컨슈머 내부 동작

반응형

http://www.yes24.com/Product/Goods/104410708

해당 책을 공부하며 정리한 내용입니다.

 

실전 카프카 개발부터 운영까지 - YES24

아파치 카프카의 공동 창시자 준 라오(Jun Rao)가 추천한 책!국내 최초이자 유일한 컨플루언트 공인 아파치 카프카 강사(Confluent Certified Trainer for Apache Kafka)와 공인 관리자 자격(Confluent Certified...

www.yes24.com


컨슈머 오프셋 관리


컨슈머 동작 중 가장 핵심은 오프셋 관리로, 카프카에서 메시지의 위치를 나타내는 위치를 오프셋이라고 한다.

  • 예를 들어 컨슈머가 일시적으로 동작을 멈추고 재시작하는 경우나, 컨슈머가 구동 중인 서버에 문제가 발생해 새로운 컨슈머가 기존 컨슈머의 역할을 대신하는 경우에는 기존 컨슈머의 마지막 메시지 위치부터 새로운 컨슈머가 메시지를 가져올 수 있어야만 장애로부터 빠르게 복구할 수 있다.
  • 컨슈머 그룹은 자신의 오프셋 정보를 __consumer_offsets 토픽에 각 컨슈머 그룹별로 오프셋 위치 정보가 기록된다.


__consumer_offsets

해당 토픽은 파티션 수와 리플리케이션 팩터 수를 갖고 있으며, 내부 토픽이지만 파티션 수와 리플리케이션 팩터 수는 브로커의 설정 파일인 server.properties에서 관리자가 원하는 값으로 변경할 수 있음.

offsets.topic.num.partitions: 기본값 50
offsets.topic.replication.factor: 기본값 3


그룹 코디네이터


컨슈머들은 하나의 컨슈머 그룹의 구성원으로 속하며, 컨슈머 그룹 내의 각 컨슈머들은 서로 자신의 정보를 공유하면서 하나의 공동체로 동작한다.

  • 컨슈머 그룹 내의 컨슈머들은 자신이 속한 컨슈머 그룹에서 떠날 수 있으며, 새로운 컨슈머가 합류할 수도 있다.
  • 따라서 컨슈머 그룹은 이러한 변화를 인지하고 각 컨슈머들에게 작업을 균등하게 분배해야 하는데, 이러한 동작을 리밸런싱이라고 한다.

컨슈머 그룹에는 안정적인 컨슈머 그룹 관리를 위해 코디네이터가 존재하는데, 그룹 코디네이터라고 한다.

  • 그룹 코디네이터의 목적은 컨슈머 그룹이 구독한 토픽의 파티션과 그룹의 멤버들을 트래킹하는 것.
  • 파티션 또는 그룹의 멤버에 변화가 생기면, 작업을 균등하게 재분배하기 위해 컨슈머 리밸런싱 동작이 발생한다.
  • 그룹 코디네이터는 각 컨슈머 그룹별로 존재하며, 이런 그룹 코디네이터는 카프카 클러스터 내의 브로커 중 하나에 위치한다.


그룹 코디네이터 동작 방식

컨슈머 그룹 동작 과정

  1. 컨슈머는 컨슈머 설정 값 중에 bootstrap.brokers 리스트에 있는 브로커에게 컨슈머 클라이언트와 초기 커넥션을 연결하기 위한 요청을 보낸다.
  2. 해당 요청을 받은 브로커는 그룹 코디네이터를 생성하고 컨슈머에게 응답을 보낸다.
  3. 그룹 코디네이터는 group.inital.rebalance.delay.ms 의 시간동안 컨슈머의 요청을 기다린다.
  4. 컨슈머는 컨슈머 등록 요청을 그룹 코디네이터에게 보낸다. 이때 가장 먼저 요청을 보내는 컨슈머가 컨슈머 그룹의 리더가 된다.
  5. 컨슈머 등록 요청을 받은 그룹 코디네이터는 해당 컨슈머 그룹이 구독하는 토픽 파티션 리스트 등 리더 컨슈머의 요청에 응답을 보낸다
  6. 리더 컨슈머는 정해진 컨슈머 파티션 할당 전략에 따라 그룹 내 컨슈머들을 파티션을 할당한 뒤 그룹 코디네이터에게 전달한다.
  7. 그룹 코디네이터는 해당 정보를 캐시 하고 각 그룹 내 컨슈머들에게 성공을 알린다.
  8. 각 컨슈머들은 각자 지정된 토픽 파티션으로부터 메시지들을 가져온다.


컨슈머들은 그룹 코디네이터와 연결되어 관리를 받게 된다.

  • 컨슈머들은 현재 자신들이 속한 컨슈머 그룹에서 빠져나갈 수도, 새롭게 합류할 수도 있다.
  • 이러한 컨슈머 그룹의 변화들은 컨슈머 코디네이터에게 컨슈머가 join 또는 leave 요청을 보냄으로써 자연스럽게 처리된다.
  • 컨슈머 장애 등 컨슈머들의 변경을 감지하기 위해 그룹 코디네이터와 컨슈머들은 서로 하트비트를 주고받는다. 하트비트를 통해 컨슈머의 상태를 확인하며, 특정 컨슈머에 문제가 발생했다고 판단되면 컨슈머 리밸런싱 동작을 통해 컨슈머 그룹의 전체 균형을 다시 맞춘다.


스태틱 멤버십


점검이나 업데이트 등의 이유로 관리자는 컨슈머 그룹 내의 컨슈머들을 하나씩 순차적으로 재시작하는 경우, 하트비트 주기, 세션 타임아웃 등의 설정으로 인해 하나의 컨슈머가 재시작될 때마다 전체 리밸런싱이 일어나면, 리밸런싱 작업이 일어나는 동안 컨슈머들은 일시 중지하므로 번거롭다.

리밸런싱이 일어나는 이유는, 컨슈머 그룹 동작에서는 각 컨슈머를 식별하기 위해 엔티티 ID를 부여하게 되는데, 컨슈머가 재시작되면, 컨슈머 그룹 내의 동일한 컨슈머임에도 새로운 컨슈머로 인식해 새로운 엔티티 ID가 부여되고 이로 인해 컨슈머 그룹의 리밸런싱이 발생하는 것이다.

대용량 메시지들을 처리하는 컨슈머 그룹이라면 리밸런싱 동작으로 인해 원래 상태를 복구하는데 상당한 시간이 소요될 수 있다.

  • 카프카에서는 이러한 불필요한 리밸런싱을 방어하기 위해 아파치 카프카 2.3버전 부터 스태틱 멤버십이라는 개념을 도입했다.

스태틱 멤버십이란 컨슈머 그룹 내에서 컨슈머가 재시작 등으로 그룹에서 나갔다가 다시 합류하더라도 리밸런싱이 일어나지 않게 한다.

  • 즉 컨슈머가 인식할 수 있는 ID를 적용함으로써 다시 합류하더라도 기존 코디네이터가 기존 구성원임을 인식할 수 있게 하는 것.
  • 추가로 스태틱 멤버십 기능이 적용된 컨슈머는 그룹에서 떠날 때 그룹 코디네이터에게 알리지 않으므로 불필요한 리밸런싱도 발생하지 않는다.


컨슈머 파티션 할당 전략


컨슈머 그룹의 리더 컨슈머가 정해진 파티션 할당 전략에 따라 각 컨슈머와 대상 토픽의 파티션을 매칭 시킨다.

파티션 할당 전략에는 partition.assignment.strategy로 표시하며, 다음과 같은 전략이 있다.

  • RangeAssignor (default)
  • RoundRobinAssignor
  • StickyAssignor
  • CooperativeStickyAssignor


레인지 파티션 할당 전략

  • 각 토픽 별로 할당 전략을 사용하게 된다.
  • 먼저 구독하는 토픽에 대한 파티션을 순서대로 나열한 후 컨슈머를 순서대로 정렬한다. 그런 다음 각 컨슈머가 몇 개의 파티션을 할당해야 하는지 전체 파티션 수를 컨슈머 수로 나눈다.
  • 컨슈머 수와 파티션 수가 일치하면 균등하게 할당될 수 있지만, 균등하게 나눠지지 않는 경우에는 앞쪽의 컨슈머들은 추가 파티션을 할당받게 된다.
  • 레인지 파티션 할당 전략은 동일한 레코드 키를 사용하고 하나의 컨슈머 그룹이 동일한 파티션 수를 가진 2개 이상의 토픽을 컨슘 할 때 유용할 수 있다.
  • 이러한 특수한 환경에서 사용하는 것이 좋지만, 컨슈머에 균등하게 파티션이 분배되지 않으므로 컨슈머 그룹은 불균형한 상태로 운영될 수 있다는 점에 유의해야 한다.


라운드 로빈 파티션 할당 전략

  • 컨슘 해야 하는 모든 파티션과 컨슈머 그룹 내 모든 컨슈머를 나열한 후 라운드 로빈으로 하나씩 파티션과 컨슈머를 할당하는 전략.


스티키 파티션 할당 전략

  • 레인지 파티션 할당 전략과 라운드 로빈 파티션 할당 전략 모두 컨슈머 그룹의 리밸런싱 동작으로 파티션 재할당 작업이 발생하면 기존에 매핑됐던 파티션과 동일한 컨슈머가 다시 매핑되리라고는 보장할 수 없다.
  • 재할당 작업이 발생하더라도 기존에 매핑됐던 파티션과 컨슈머를 최대한 유지하려고 하는 전략.
  • 스티키 파티션 할당 전략은 두 가지 목적으로 컨슈머에 파티션을 할당한다.
    • 가능한 균형 잡힌 파티션 할당
    • 재할당이 발생할 때 되도록 기존의 할당된 파티션 정보를 보장하는 것
    • (참고로 첫 번째 목적의 우선순위가 더 높아 무조건 기존의 파티션과 컨슈머를 유지하지는 않는다.)


협력적 스티키 파티션 할당 전략

기존의 리밸런싱 동작 방식

  • 스티키 전략과 동일한 방식이지만, 컨슈머 그룹 내부의 리밸런싱 동작이 한 층 고도화됐다는 차이가 존재.
  • 위의 모든 컨슈머 리밸런싱 동작에서는 내부적으로 EAGER라는 리밸런스 프로토콜을 사용했고, EAGER 프로토콜은 컨슈머 리밸런싱 동작 시 컨슈머에 할당된 모든 파티션을 항상 취소했다.
    • 컨슈머들의 파티션 소유권 변경 때문
    • 그룹 내에서 여러 파티션들에 대해 소유권 변경 작업이 동시에 이뤄져야 하므로 이러한 로직을 단순하게 구현하기 위해서
  • 이렇게 리밸런싱 동작에서 컨슈머에 할당된 모든 파티션을 취소했으므로 컨슈머 그룹 전체에서 컨슈머와 파티션 재할당이 가능했고 한 번의 리밸런싱 동작으로 모든 컨슈머와 파티션 매핑을 할 수 있었다.
    • 하지만 리밸런싱에서 모든 파티션 할당을 취소하는 동작은 리소스를 많이 사용하는 컨슈머 그룹에서는 큰 문제가 된다. (컨슈머들의 다운타임)


리밸런싱 동작 방식

  1. 컨슈머의 다운됨을 감지
  2. 컨슈머에게 할당된 모든 파티션을 제거한다. (컨슈머의 다운타임 시작)
  3. 구독한 파티션이 컨슈머들에게 재 할당된다.


협력적 스티키 파티션 할당 전략 리밸런싱 동작 방식

이러한 이슈를 개선하기 위해 협력적 스티키는 내부 리밸런싱 프로토콜을 EAGER가 아닌 COOPERTATIVE 프로토콜을 적용하고, 리밸런싱이 동작하기 전의 컨슈머 상태를 유지할 수 있게 한다.

  • 기존의 리밸런싱 동작은 한 번에 모든 파티션 할당 작업이 끝난다는 장점이 있지만, 전체 컨슈머가 일시적으로 멈춘 상태에서 리밸런싱이 이뤄진다는 제약이 존재.
  • 협력적 스티키 할당 전략에서는 되도록 동작중인 컨슈머들에게 영향을 주지 않는 상태에서 몇 차례에 걸쳐 리밸런싱이 일어난다.


협력적 리밸런싱 동작 방식

  1. 컨슈머 그룹에 새로운 컨슈머가 합류하며 리밸런싱이 트리거가 된다.
  2. 컨슈머 그룹 내 컨슈머들은 그룹 합류 요청과 자신들이 컨슘 하는 토픽의 파티션 정보를 그룹 코디네이터로 전송한다.
  3. 그룹 코디네이터는 해당 정보를 조합해 컨슈머 그룹의 리더에게 전송한다.
  4. 컨슈머 그룹의 리더는 현재 컨슈머들이 소유한 파티션 정보를 활용해 제외해야 할 파티션 정보를 담은 새로운 파티션 할당 정보를 컨슈머 그룹 멤버들에게 전달한다.
  5. 새로운 파티션 할당 정보를 받은 컨슈머 그룹 멤버들은 현재의 파티션 할당 전략과 차이를 비교해보고 필요 없는 파티션을 골라 제외한다. 이전의 파티션 할당 정보와 새로운 파티션 할당 정보가 동일한 파티션들에 대해서는 어떤 작업도 수행할 필요가 없다.
  6. 제외된 파티션 할당을 위해 컨슈머들은 다시 합류 요청을 한다. 여기서 두 번째 리밸런싱이 트리거 된다.
  7. 컨슈머 그룹의 리더는 제외된 파티션을 적적한 컨슈머에게 할당한다.

정리하면, 협력적 스티키 전략은 아파치 카프카 2.4에서 처음 공개되어 2.5 버전에서 안정화됐고, 최신 버전의 카프카를 사용하는 컨슈머들은 리밸런싱으로 인한 다운타임을 최소화할 수 있게 됐다.

  • 컨슈머의 영향을 최소화하기 위해 점진적으로 리밸런싱이 진행되더라도, 최종적으로 컨슈머들은 균형 잡힌 분산을 하데 된다.
  • 이러한 장점으로 관리자들은 컨슈머의 확장 및 축소, 롤링 재시작 등의 작업 진행 시 컨슈머 리밸런싱에 대한 부담을 줄일 수 있게 됐다.
반응형