Kafka Message Delivery Semantics 과 Acks 설정

김아별 · 원프레딕트 백엔드 엔지니어
April 24, 2024

Motor 제품이 외부와 공동 프로젝트 진행을 위해 새로운 Kafka 환경을 구축해야 했습니다. 프로젝트에 대해 간단히 설명드리면, 계측기를 통해 나온 전류/전압 데이터를 Kafka의 메시지를 전달받아, 모터 상태를 진단하는 프로젝트입니다. 지금부터는 이 전달받은 메시지의 전달 보장 수준과 이를 위한 프로듀서 설정을 정하기 위해 조사했던 내용을 말씀드리겠습니다.

Kafka Message Delivery Semantics와 설정 방법

Kafka Message Delivery Semantics란?

Kafka의 Message Delivery Semantics는 Producer의 메시지 전달 보장 수준을 의미합니다. Message Delivery Semantics는 메시지 전달 보장 수준에 따라 At most once, At least once, Exactly once 3단계로 나뉩니다.

메시지 전달 보장 수준 3단계

At most once

메시지가 최대 한 번 전달되는 가장 약한 보장 수준입니다. 시스템 장애가 발생하면 메시지 유실의 가능성이 있지만, 재전송하지 않습니다. 프로듀서는 리더에게 메시지를 보낸 후에 확인을 기다리지 않으며, 속도는 빠르지만 메시지 손실의 위험이 있습니다.

At least once

메시지가 적어도 한 번 이상 전달됩니다. 시스템 장애가 발생해도 메시지가 손실되지는 않지만, 중복 전달이 발생할 수 있습니다. 프로듀서는 리더에게 메시지를 보낸 후에 확인을 받기를 기다리며, 이에 따라 메시지의 중복 전달이 발생할 수 있습니다.

Exactly once

메시지가 정확히 한 번만 전달됩니다. 가장 높은 보장 수준입니다. 시스템의 일부에 장애가 발생하더라도 메시지가 손실되거나 두 번 읽히지 않습니다. 처리 비용이 상대적으로 높을 수 있습니다. 프로듀서는 리더에게 메시지를 보내고 모든 팔로워 브로커가 확인받을 때까지 기다립니다.

Producer Leader Partition, Replica Set

leader-partition.png

프로듀서 파티셔너는 각 메시지를 토픽 파티션에 매핑하고 프로듀서는 해당 파티션의 리더에게 작성 요청을 보냅니다. Kafka 클러스터의 각 파티션에는 브로커 사이에 리더와 복제본 세트(Replica Set)가 있습니다. 이 복제본들을 팔로워 파티션이라고 부르기도 합니다. 파티션에 대한 모든 쓰기는 파티션 리더를 거쳐야 합니다. 복제본은 리더에서 가져와서 동기화된 상태로 유지됩니다. 리더가 종료되거나 실패하면 동기화된 복제본 중에서 다음 리더가 선출됩니다.

Producer Acks 설정

프로듀서가 메시지가 전달되었는지 확인하기 위해 acks 옵션이 있습니다. acks 는 프로듀서가 쓰기 요청이 완료된 것으로 간주하기 전에 요구하는 승인 수입니다. acks 옵션에는 0, 1, all 3가지가 있습니다.

producer_acks.png

acks = 0

acks_0.png

acks = 0인 프로듀서는 브로커가 메시지를 수락할 때까지 기다리지 않고 메시지를 전송한 순간 바로 메시지를 "성공적으로 작성된 것"으로 간주합니다. 즉, 메시지가 정말로 잘 전달되었는지 확인하지 않습니다. At most once 를 위한 acks 설정입니다.

acks = 1

acks_1.png

acks = 1인 경우, 프로듀서는 리더만 메시지를 승인한 경우 메시지를 "성공적으로 작성된 것"으로 간주합니다. 리더 응답이 요청되지만, 백그라운드에서 이루어지므로 복제가 보장되지는 않습니다. 응답을 받지 못하면 프로듀서가 요청을 다시 시도할 수 있습니다. 리더 브로커가 예기치 않게 오프라인 상태가 되었는데 복제본이 아직 데이터를 복제하지 않은 경우 데이터 손실이 발생합니다. At least once 를 달성하기 위한 설정값입니다.

acks = all

acks_all.png

acks = all은 acks = -1과 동일한 의미를 가지며, 세 가지 방법 중 가장 느리지만 메시지가 도착했고 여러 디스크에 기록되었다는 큰 보장 수준을 제공합니다. 이 경우 프로듀서는 모든 동기화 복제본(in-sync replicas, ISR)에서 메시지를 수락하면 메시지를 "성공적으로 작성된 것"으로 간주합니다. 이 설정을 하게 되면 먼저, 파티션의 리드 복제본은 메시지를 안전하게 쓰기 위한 ISR이 충분한지 확인합니다. 요청은 리더가 팔로워 복제본이 메시지를 복제했음을 확인할 때까지 버퍼에 저장되며, 이 시점에서 클라이언트에 성공적인 승인 메시지가 다시 전송됩니다. min.insync.replicas는 토픽과 브로커 수준에서 모두 구성할 수 있습니다. 데이터는 동기화 중인 모든 복제본(min.insync.replicas)에 쓰여질 때 커밋된 것으로 간주됩니다. 값이 2이면 ISR인 최소 2개의 브로커(리더 포함)가 데이터를 가지고 있다고 응답해야 한다는 의미입니다. acks = all 은 Exactly once를 달성하기 위한 옵션 중 하나입니다.

enable_idempotence.png

Exactly once를 달성하기 위해서는 acks 옵션뿐만 아니라 enable.idempotence = true 설정도 필요합니다. enable.idempotence값을 true로 하면 Exactly once를 달성할 수 있습니다. idempotence 설정은 브로커에게 ProducerID(PID) 를 전송하여 중복체크를 할 수 있게 전송하게 됩니다. 'true'로 설정하면 생산자는 각 메시지의 정확히 하나의 복사본이 스트림에 기록되도록 보장합니다. 'false'인 경우 브로커 오류 등으로 인해 생산자가 재시도하면 재시도된 메시지의 중복이 스트림에 기록될 수 있습니다.

마치며

지금까지 Kafka Message Delivery Semantics 3가지와 이를 위한 Producer Acks 설정에 대해 알아보았습니다. 사실 완벽한 Exactly once을 달성하기 위해서는 추가적인 설정이 몇 가지 더 필요합니다. 더 깊은 이해가 필요하신 분, Kafka에 대한 조예가 깊으신 분은 저희 원프레딕트에 지원하셔서 함께 탐구해 가면 좋겠습니다!😉

원프레딕트는 더 나은 제품을 고민하며 기술적인 문제를 함께 풀어낼 동료를 찾고 있습니다.
자세한 내용은 채용 사이트를 참고해 주세요.