tech/database

[Kafka] 카프카 프로듀서

daniel_lab 2024. 9. 21. 23:14

Kafka는 대용량 데이터의 실시간 처리를 위한 분산 스트리밍 플랫폼이다. 오늘은 Kafka 프로듀서가 메시지를 브로커의 토픽 파티션에 적재하는 과정과 메시지 전송의 신뢰성을 높이기 위한 주요 설정값들에 대해 정리한다.

1. 프로듀서에서 브로커의 토픽 파티션으로 메시지 전송 과정

Kafka 프로듀서는 애플리케이션에서 생성된 메시지를 브로커의 특정 토픽 파티션에 안전하게 전달하는 역할을 수행한다. 이 과정에서 메시지가 파티셔너를 거쳐 브로커에 적재되고 응답을 받기까지의 구체적인 흐름을 단계별로 설명한다.

1. 메시지 생성 및 전송 요청

프로듀서는 애플리케이션으로부터 전송할 데이터(record)를 생성한다. 이 데이터는 키(key)와 값(value), 그리고 선택적인 헤더(headers)로 구성된다. 프로듀서는 이 데이터를 전송하기 위해 send() 메서드를 호출한다.

2. 직렬화(Serialization)

프로듀서는 메시지를 네트워크로 전송하기 전에 바이트 배열로 변환해야 한다. 이를 위해 키와 값에 대해 각각 설정된 Serializer를 사용하여 직렬화한다.

3. 파티셔닝(Partitioning)

메시지가 토픽의 어떤 파티션에 할당될지 결정되는 과정은 다음과 같다.

  • 키가 존재하는 경우: 파티셔너는 키의 해시 값을 기반으로 토픽의 파티션 수로 나눈 나머지를 사용하여 파티션을 결정한다. 이를 통해 동일한 키는 항상 동일한 파티션에 매핑된다.
  • 키가 없는 경우: 프로듀서는 라운드 로빈(round-robin) 방식이나 스티키 파티셔너(sticky partitioner)를 사용하여 파티션을 선택한다.

파티션이 결정되면 메시지에 해당 파티션 번호가 할당된다.

4. 배치 처리 및 버퍼링

프로듀서는 성능 향상을 위해 메시지를 배치(batch)로 묶어 전송한다. 각 파티션마다 배치가 생성되며, 배치 크기는 batch.size 설정값에 따라 결정된다. 메시지는 배치에 추가되어 메모리 버퍼에 일시적으로 저장된다.

  • linger.ms 설정: 배치가 가득 차지 않아도 일정 시간(linger.ms) 동안 메시지를 모아 배치를 형성할 수 있다.
  • 메모리 관리: 프로듀서의 전체 버퍼 크기는 buffer.memory로 제한되며, 버퍼가 가득 차면 send() 호출은 블록되거나 예외를 발생시킨다.

5. 브로커로 메시지 전송

배치가 준비되면 프로듀서는 해당 파티션의 리더 브로커로 네트워크 요청을 보낸다.

  • 네트워크 연결: 프로듀서는 브로커와의 TCP 연결을 설정하거나 기존 연결을 재사용한다.

6. 브로커에서 메시지 처리

브로커는 프로듀서로부터 받은 Produce Request를 처리한다

  • 메시지 저장: 브로커는 메시지를 해당 파티션에 적재한다.각 메시지에는 고유한 오프셋(offset)이 할당된다.
  • ISR 업데이트: 리더 파티션은 팔로워 파티션들에 복제를 위한 메시지를 전송한다.

7. 응답 생성 및 전송

브로커는 프로듀서에게 Produce Response를 반환한다. 이 응답에는 다음 정보가 포함된다

  • 오프셋 정보: 각 메시지의 오프셋을 포함한다.
  • 에러 코드: 처리 중 발생한 오류가 있으면 해당 오류 코드를 포함한다.

응답 시점은 acks 설정에 따라 달라진다

  • acks=0: 프로듀서는 브로커의 응답을 기다리지 않고 메시지를 전송한다(유실 가능성 존재)
  • acks=1: 리더 브로커가 메시지를 받으면 응답한다(유실 가능성 존재)
  • acks=all 또는 acks=-1: 리더와 모든 ISR(In-Sync Replicas)이 메시지를 받았을 때 응답한다. 유실가능성은 없지만 브로커가 응답하려고할때 죽으면 프로듀서가 재시도를 통해 중복해서 전송할 가능성은 있음. 이를 방지하기위해 idempotence.enabled 설정을 true 로 하는것이 필요하다.

2. Producer 주요 설정값들

acks(위에서 기술)

delivery.timeout.ms

  • 프로듀서가 메시지 전송을 시도하는 최대 시간을 밀리초 단위로 설정한다. 이 시간이 지나면 전송을 포기하고 오류를 반환한다.

retries

  • 전송 실패 시 재시도할 횟수를 설정한다.

retry.backoff.ms

  • 전송 실패 후 재시도하기 전에 대기하는 시간을 밀리초 단위로 설정한다.

enable.idempotence

  • 멱등성(idempotence)을 활성화하여 중복 메시지 전송을 방지한다. 이 설정이 활성화되면 전송되는 메시지에 sequence number가 붙게 되어 동일한 메시지가 프로듀서에 의해 중복 전송되더라도 브로커에서 중복적재를 방지하게된다.

3. 정확히 한 번 적재를 만족하기 위한 설정 방법

정확히 한 번(exactly-once) 메시지가 적재되도록 보장하려면 중복 전송과 메시지 손실을 모두 방지해야 한다. 이를 위해 다음과 같이 설정한다:

  • enable.idempotence=true: 멱등성을 활성화하여 중복 전송을 방지한다.
  • acks=all: 메시지의 안정적인 적재를 보장한다.
  • retries를 충분히 큰 값으로 설정: 전송 실패 시 재시도를 통해 메시지 손실을 방지한다.