[Kafka] Kafka 프로듀서(Producer) 이해하기
l Kafka
카프카는 메시지를 생산, 발송하는 프로듀서(producer)와 메시지를 수신, 소비하는 컨슈머(consumer)가 있으며, 프로듀서와 컨슈머 사이에서 메시지를 중개하는 브로커(broker)로 구성된다. 이번 포스트는 프로듀서에 대해서 알아본다.
메시지를 생산(producer)해서 카프카의 토픽으로 메시지를 보내는 역할을 하는 애플리케이션, 서버 등을 모두 프로듀서라고 한다. 프로듀서의 주요 기능은 각각의 메시지를 토픽 파티션에 매핑하고 파티션의 리더에 요청을 보내는 것이다. 이때 키 값을 정해 해당 키를 가진 모든 메시지를 동일한 파티션으로 전송할 수 있으며, 키를 지정하지 않으면 라운드 로빈 방식으로 파티션에 균등하게 배분한다.
프로듀서는 아래 과정을 통해서 메시지를 브로커로 전달한다.
1. Serialize
2. Partition
3. Compress
4. Accumulate records
5. Group by broker and send
[Serialize]
프로듀서 레코드가 프로듀서에게 전달된 직렬 변환기를 기반으로 직렬화된다. 키와 값은 모두 전달된 직렬 변환기를 기반으로 직렬화된다. 일부 직렬 변환기에는 문자열 직렬 변환기, byteArray 직렬 변환기 및 ByteBuffer 직렬 변환기가 포함된다.
[Partitioner]
프로듀서는 레코드를 기록해야하는 주제의 파티션을 결정한다. 기본적으로 murmur2 알고리즘이 파티셔닝에 사용된다. Murmur 2 알고리즘은 전달된 키를 기반으로 고유한 해시 코드를 생성하고 적절한 파티션이 결정된다. 키가 전달되지 않은 경우 라운드 로빈 방식으로 파티션이 선택된다.
동일한 키를 레코드 세트에 전달함으로써 Kafka는 주어진 수의 파티션에 대해 수신된 순서대로 동일한 파티션에 메시지가 기록되도록 보장한다는 점을 이해하는 것이 중요하다. 수신된 메시지의 순서를 유지하려면 메시지에 적절한 키를 사용하는 것이 중요하다. 사용자 정의 파티셔너를 프로듀서에게 전달하여 메시지를 써야 하는 파티션을 제어할 수도 있다.
[Compression]
프로듀서 레코드가 레코드 누산기에 기록되기 전에 압축된다. 기본적으로 Kafka 생산자에서는 압축이 활성화되어 있지 않다. 지원되는 압축 유형은 다음과 같다.
[Record Accumulator]
레코드가 주제의 파티션당 버퍼에 누적된다. 레코드는 프로듀서 배치 크기 속성에 따라 배치로 그룹화된다. 주제의 각 파티션은 별도의 누산기/버퍼를 갖는다.
[Sender thread]
레코드 누산기의 파티션 배치가 전송될 브로커별로 그룹화된다. 배치의 레코드는 batch.size 및 linger.ms 속성을 기반으로 브로커로 전송된다. 레코드는 정의된 배치 크기에 도달하거나 정의된 지연 시간에 도달한 경우로 두 가지 조건에 따라 프로듀서가 전송한다.
[Duplicate message detection]
Kafka에서 메시지를 커밋했지만 네트워크 오류 및 기타 문제로 인해 프로듀서가 승인을 받지 못한 경우 프로듀서는 중복된 메시지를 보낼 수 있다. 이 경우 중복 메시지를 피하기 위해 Kafka는 생산자 ID 및 시퀀스 번호를 기반으로 각 메시지를 추적한다. 동일한 생산자 ID 및 시퀀스 번호를 가진 커밋된 메시지에 대해 중복 메시지가 수신되면 Kafka는 해당 메시지를 중복 메시지로 처리하고 프로듀서가 메시지를 처리할 수 있도록 승인을 프로듀서에게 다시 보낸다.
[프로듀서의 주요 설정]
l bootstrap.servers : 카프카 클러스터는 마스터라는 개념이 없기 때문에 클러스터 내 모든 서버가 클라이언트 요청을 받을 수 있다. 그래서 전체 카프카 호스트 정보를 입력한다. 특정 노드의 정보만 사용해도 되지만 해당 노드가 장애시 접속이 불가능하기 때문에 전체 노드 정보를 입력하는 것을 추천한다.
l key.serializer : 메시지의 키를 직렬화 할 때 사용할 클래스를 설정한다. 직렬화 클래스의 경로를 입력한다.
l value.serializer : 메시지의 값을 직렬화 할 때 사용할 클래스 설정한다. 직렬화 클래스의 경로를 입력한다.
l partitioner.class : 파티셔너로 사용할 클래스 설정한다. 해당 클래스 경로를 넣으며, 기본 값은 카프카에서 제공하는 DefaultPartitioner 클래스에 대한 경로이다.
l compression.type : 압축 타입에 관한 설정으로 어떤 타입으로 압축할 것인지 정할 수 있다.
l buffer.memory : Record Accumulator에서 사용할 메모리의 총 양에 관한 설정으로 해당 설정 값을 초과하면 프로듀서가 정상 동작하지 않는다.
l batch.size : 레코드 배치의 크기에 관한 설정(bytes)으로 프로듀서가 카프카 서버로 데이터를 보내기 위하 잠시 대기(배치 전송이나 딜레이)할 수 있는 전체 메모리 바이트 이다. 레코드 배치가 해당 설정 값에 다다르면 메시지를 전송한다.
l linger.ms : 레코드 배치의 최대 전송 대기 시간 설정(ms)으로, batch.size에 만족하지 않더라도 레코드 배치는 이 설정에 따라 전송된다. 기본값은 0이며 즉시 전송한다. 0 보다 큰 경우 해당 시간만큼 지연되어 처리된다.
l retires : 일시적인 오류로 인해 전송에 실패한 데이터를 재전송 하는 횟수에 관한 설정이다.
l max.in.flight.requests.per.connection : 프로듀서가 응답 여부에 상관없이 한 번에 보낼 수 있는 요청 횟수에 관한 설정. 2 이상이면 한 번의 연결에서 2개 이상의 메시지 전송 요청을 보낼 수 있다.
l acks : 프로듀서가 전송 후 브로커의 응답을 기다리는 설정이다. 해당 옵션의 값이 작으면 성능이 좋지만, 메시지 손실 가능상이 있고, 반대로 크면 성능이 좋지 않지만 메시지 손실 가능성이 적어진다.
ü Acks=0 : 프로듀서는 서버로부터 어떠한 응답을 기다리지 않는다. 이 경우 서버가 데이터를 받았는지 보장하지 않고, 클라이언트는 전송 실패에 대한 결과를 알지 못하게 때문에 재요청 설정도 적용되지 않는다. 서버로부터 ack에 대한 응답을 기다리지 않기 때문에 매우 빠르게 메시지를 보낼 수 있어 높은 처리량을 얻을 수 있다.
ü Acks=1 : 리더는 데이터를 기록하지만 모든 팔로워는 확인하지 않는다. 이 경우 일부 데이터의 손실이 발생할 수 있다.
ü Acks=all 또는 -1 : 만약 all 또는 -1로 설정하는 경우 리더는 ISR 팔로워로부터 데이터에 대한 복제가 완료될 때까지 ack를 기다린다. 하나 이상의 팔로워가 있는 한 데이터는 손실되지 않으며 데이터 무손실에 대해 가장 강력하게 보장한다.
[3개의 브로커 노드 구성에서 메시지 손실을 방지하기 위한 프로듀서의 acks 설정과 브로커의 min.insync.replicas 설정]
l acks=all과 브로커의 min.insync.replicas=1 : 메시지 손실을 허용하지 않도록 프로듀서의 acks 설정은 all로 지정한다. 이때 브로커의 min.insync.replicas 팩터 값을 1로 설정할 경우 리더에 메시지가 저장되면 ack 값을 보내기 때문에 acks=all로 설정했지만 acks=1과 동일하게 작동한다. 카프카에서는 프로듀서만 acks=all로 메시지를 보낸다고 해서 손실 없는 메시지를 보장해주지 않는다.
l acks=all과 브로커의 min.insync.replicas=2 : 메시지 손실을 허용하지 않도록 프로듀서의 acks 설정은 all로 지정한다. 이때 브로커의 min.insync.replicas 팩터 값을 2로 설정한다. 팔로워는 리더로부터 변경사항이 있는지 주기적으로 확인하며 데이터를 복제한다. 그리고 리더는 min.insync.replicas=2로 설정되어 있기 때문에 acks를 보내기전 최소 2개의 리플리케이션을 유지하는지 확인한다. 만약 리더가 acks를 보내자마자 리더 선출작업이 발생해도 그 메시지를 가지고 있는 팔로워가 있기 때문에 메시지 손실은 발생하지 않는다. 아파치 카프카 문서에서는 손실 없는 메시지 전송을 위한 조건으로 프로듀서는 acks=all, 브로커의 min.insync.replicas=2, 토픽의 리플리케이션 팩터는 3으로 권장하고 있다.
l acks=all과 브로커의 min.insync.replicas=3 : 리플리케이션 팩터3에서, min.insync.replicas=3으로 설정된 경우, 리더, 팔로워 합쳐 3개의 복제본이 유지되어야만 acks를 응답한다. 따라서 하나의 노드라도 장애가 발생하면 옵션값을 만족하지 못하기 때문에 오류가 발생한다.
[참고자료]
https://www.linkedin.com/pulse/kafka-producer-overview-sylvester-daniel/
2024-01-22 / Sungwook Kang / https://sungwookkang.com
KAFKA, 아파치 카프카, Apache Kafka, 카프카 토픽, 카프카 파티션, Kafka Topic, Kafka Partition, 카프카 복제, Kafka Replication, 프로듀서, Producer, Kafka Producer, 카프카 프로듀서
'SW Engineering > DevOps, SRE' 카테고리의 다른 글
[Kafka] Kafka와 Debezium을 활용하여 SQL Server의 데이터를 실시간으로 PostgreSQL로 복제하기 (0) | 2024.02.26 |
---|---|
[Kafka] Kafka 컨슈머(Consumer) 이해하기 (0) | 2024.01.23 |
[Kafka] Kafka 리더, 팔로워, 복제 및 복구 이해하기 (0) | 2024.01.19 |
[Kafka] Kafka 데이터 모델인 Topic과 Partition 이해하기 (0) | 2024.01.18 |
[Kafka] Kafka 클러스터 4노드 구성 - Controller, Broker 혼합해서 구성하기 (0) | 2024.01.17 |