안녕하세요~! 다시 찾아왔습니다.
우리는 이전에 kafka consumer 에 대한 동작원리를 알아보았어요
https://huisam.tistory.com/entry/kafka-rebalancing?category=849126
저번 시간에 Producer 에 대한 자세한 이야기를 하지 못해서 ㅎㅎ
오늘은 Kafka Producer 에 대한 설명을 해보겠습니다.
Producer
먼저 설명을 드리기에 앞서서 Producer 의 역할은 뭘까요?
제가 생각하는 Kafka 의 Producer 의 역할은 Broker 에게 메세지를 전송하는 책임을 가지고 있습니다.
Producer 는 데이터를 어떻게 전송할 것인지에 대한 전략을 가지고 있게 되는 것이죠
- 어떤 Serializer 를 이용하여 데이터를 전송할 것인가
- 데이터에 대한 Compression 을 하여 데이터를 전송할 것인가
- 어떤 Partition 에게 데이터를 전송할 것인가
- 재시도에 대한 전략을 어떻게 할 것인가?
위 4가지의 핵심 전략들을 바탕으로 이루어지게 되는 것입니다.
1가지씩 자세하게 알아보도록 할까요?
Serializer
직렬화 전략에 대한 선택은 크게 2가지 입니다.
key 는 Partition 을 선택할 때 기준값을 사용하게 되는 데이터입니다.
value 는 kafka topic 데이터에 직접적으로 전송하기 위한 데이터입니다.
Configuration | Default | Description |
key.serializer | - | key 를 serialize 하는 방법에 대한 전략 |
value.serializer | - | value 를 serialize 하는 방법에 대한 전략 |
따라서 2가지 데이터에 대해 직렬화 전략을 선택해주시면 됩니다.
Compression
Compression 을 한글로 해석하면 압축입니다.
흔히 client 사이드에서 데이터에 대한 용량이 커지면 네트워크 비용이 많이 발생하니, 압축해서 전송하는 전략을 선택하기 위함입니다.
압축되는 단위는 ProducerRecord 단위로 압축하게 됩니다.
Configuration | Default | Description |
compression.type | none | Producer Record 데이터에 대한 압축 전략 ( gzip, snappy, lz4, ztsd ) |
Partitioner
Partitioning 이라는 용어는 Record 가 어떤 Partition에게 전송될 것인지 선택하는 전략입니다.
위에서 우리는 Key 데이터를 직렬화 한다고 했었는데요. 바로 이 Key 데이터를 기반으로 선택하게 됩니다.
Configuration | Default | Description |
partitioner.class | org.apache.kafka.clients.producer.internals.DefaultPartitioner | Partitioner 에 대한 전략을 선택 - DefaultPartitioner: key 가 존재하면 hash 값을 기반으로 선택, key 가 존재하지 않으면 UniformStickyPartitioner 전략으로 구현되어 있음 - RoundRobinPartitioner: Partition의 순서대로 하나씩 할당한다 - UniformStickyPartitioner: batch.size 가 꽉차거나 linger.ms 값이 초과되었을 때 쌓아둔 데이터를 하나의 Partition 에게 모두 전송한다 |
batch.size | 16384 | Producer 가 데이터를 전송할 수 있는 최대 데이터 크기. 참고로 batch size 만큼 무조건적으로 전송하는게 아닌 최대 임계값 |
linger.ms | 0 | Producer 가 데이터를 전송하는데 대기하는 시간. 대기하는 시간만큼 batch size 만큼 데이터의 용량을 쌓아둘 수 있음 |
위 3가지 옵션만 이해하면 상황에 따라 Producer 의 성능을 튜닝할 수 있습니다.
아무래도 UniformStickyPartitioner 가 많이 헷갈릴 수 있는데요.
즉 쉽게 말씀드리면 batch size 만큼 어떤 partition 에게 record 를 전송할 것인지 나뉘게 되는 것이죠.
성능에 대한 의구심이 들 수 있지만, DefaultPartitioner 의 전략도 key 가 존재하지 않으면 sticky 방식을 선택한 것처럼
많이 좋다고는 합니다.
왜냐하면, linger.ms 의 값을 적당한 값으로 튜닝하게 되면, 항상 네트워크 비용이 발생하는 것이 아니라
batch 처리를 통해 네트워크 비용을 아끼고 한번에 처리가 가능하니까요
대신에 batch 일괄 처리를 위해 메모리를 조금 더 사용하게 되겠죠?
자세한 것은 아래 링크를 참고해주세요!
https://www.confluent.io/blog/apache-kafka-producer-improvements-sticky-partitioner/
재시도 전략
- Producer 가 메세지를 전송하다 실패하면 어떻게 될까요?
- 어떻게 하면 메세지를 전송에 성공했다 라고 알 수 있을까요?
자세한 것은 설정값과 함께 탐구해보도록 하겠습니다.
Configuration | Default | Description |
retries | 2147483647 | 오류로 인해 실패한 record 전송 이력에 대해 재시도하는 횟수. 단 무한정으로 재시도하는게 아니라 delivery.timeout.ms 내에서만 재시도 따라서 client 는 retries 설정값으로 튜닝하는게 아닌 timeout 값으로 튜닝할 것을 권고 |
delivery.timeout.ms | 120000ms = 2min | Producer 의 send 호출이 성공 또는 실패로 보고하는 최대 시간의 임계값 delivery.timeout.ms >= linger.ms + request.timeout.ms 를 준수할 것 |
linger.ms | 0 | Producer 가 데이터를 전송하는데 대기하는 시간. 대기하는 시간만큼 batch size 만큼 데이터의 용량을 쌓아둘 수 있음 |
request.timeout.ms | 30000 = 30second | Producer client 가 요청응답을 기다리는 최대시간 |
흔히 retries 설정값을 통해서 재시도를 제어할려고 하지만, 사실은 delivery.timeout 의 설정값을 기반으로 세팅해야 됩니다.
하지만 재시도를 할 때 어떻게 보면 record 가 중복 저장되는 이슈가 있을 수가 있어요.
예를 들면, network timeout 이슈가 발생했을 때 client 가 응답을 받지 못하면 재시도를 하기 때문이죠.
ack 가 도달하지 못하였을 때, 재시도를 하게 되므로 이 경우에는 메세지 중복이 생길 수 있게 되는 것이죠.
그렇다면 ack 는 어떻게 정해지고, 메세지 중복에 대한 발행을 어떻게 방지할 수 있을까요?
Configuration | Default | Description |
acks | all | Producer 가 요청을 보내고 Partition의 Leader 가 Replication 의 수신을 확인해야되는 개수. - 0: Producer 는 통보만 하고 수신여부를 확인하지 않음 - 1: Leader 의 Partition 에는 기록했지만, Replication 에게는 이제 기록해야됨을 수신 확인으로 통보 - all: 모든 Partition 에게 기록되었는지 확인을 통보받음 |
enable.idempotence | true | Producer 가 Record 쓰기 작업을 단 한번만 허용할 것인지 멱등성을 보장 |
enable.idempotence 는 어떻게 동작하게 되냐면..
바로 PID 라는 ProducerId 를 통해서 어떤 Producer 가 어떤 record 를 기록하게 되는지 체크하게 됩니다.
Producer 가 PID 를 지정하여 보내게 되면 처리하는 Broker 에서 PID 값을 기반으로
Record 에 대한 쓰기 작업을 단 한번만 하도록 중복 체크할 수 있게 되는 것이죠
위 option 은 message delivery semantics 과 이어지는
Producer 측에 대한 멱등성 보장에 대한 option 이므로 매우매우 중요합니다
따라서 꼭 기억해둡시다 ㅎㅎ
정리하며
오늘은 Producer 의 동작 flow 와 어떻게 Producer 가 메세지를 전송하며 멱등성을 보장할 수 있는지 알아보았습니다.
많이 어지럽지만, 각각의 구성요소에 의해 전송하게 되므로 구성요소들을 한번 정리해보면 좋겠네요 :)
다음은 Producer, Consumer 를 종합한 Kafka의 Message Delivery Semantics 에 대하여 알아보도록 하겠습니다.
참고
Take a Deep dive into the kafka Producer API
Kafka Producer Client Internals
Kafka documentation configuration
'Developer > Stream' 카테고리의 다른 글
Kafka Message Delivery Semantics - Exactly Once 는 정말 가능할까? (9) | 2022.05.07 |
---|---|
Apache Kafka Consumer - Consumer Deep Dive 하기 HeartBeat & Rebalancing 이란? (0) | 2021.08.14 |
Apache Kafka - 메세지 브로커에 대해 알아보자 (0) | 2021.03.01 |