Message Delivery Semantics
Kafka가 프로듀서에서 컨슈머까지 메시지를 전달할 때 보장하는 신뢰성 수준을 조절할 수 있으며, 이는 시스템의 요구사항에 따라 성능과 데이터 신뢰성 사이의 균형을 맞추는 중요한 설정이다.
At-most-once(최대 한 번 전송)
메시지가 유실될 수는 있지만 절대 중복되지는 않음을 보장하는 의미로, 가장 낮은 신뢰성 수준을 제공하며 최고의 성능을 목표로 할 때 사용된다.
Producer:
acks=0
설정send()
요청 후 브로커의 응답을 전혀 기다리지 않아, 네트워크 왕복 시간(RTT)을 절약브로커 장애, 일시적인 네트워크 단절 시 메시지 유실
Consumer: 메시지를 처리하기 전 오프셋을 먼저 커밋
자동 커밋 시, 메시지 처리 시간이
auto.commit.interval.ms
보다 길 경우, 처리 전에 커밋이 발생할 수 있어 유실 가능
At-least-once(최소 한 번 전송)
메시지가 중복될 수는 있지만 절대 유실되지는 않음을 보장한다는 의미로, 대부분의 애플리케이션에서 기본적으로 채택하는 신뢰성 수준이다.
Producer:
acks=all
/retries > 0
설정프로듀서는 ISR의 모든 브로커가 메시지를 받았음을 확인할 때까지 대기
브로커가 메시지를 성공적으로 저장했지만, 프로듀서에게
Ack
를 보내기 전에 네트워크 문제나 장애가 발생하면, 프로듀서는 타임아웃으로 실패를 감지하고 메시지 재전송이 시점에 브로커에는 동일한 메시지가 두 번 기록될 수 있음
Consumer: 메시지 처리를 완료한 후에 오프셋을 수동으로 커밋
enable.auto.commit=false
설정poll()
로 받은 메시지 배치의 처리가 모두 끝난 후commitSync()
또는commitAsync()
호출메시지 처리는 성공했지만,
commitSync()
호출 전에 컨슈머 애플리케이션에 장애가 발생하면, 다시 메시지를 읽어와 이전에 처리했던 메시지 중복 발생중복 처리를 방지하기 위해 멱등성을 고려한 설계 필요
이 전송 방식은 컨슈머의 멱등성을 보장하는 것이 중요한데, 이를 구현하기 위한 방법의 예시는 다음과 같다.
데이터베이스 활용: 메시지의 고유 키(예: 이벤트 ID, 주문 ID)를 데이터베이스의 Primary Key나 Unique Key로 사용하여 중복
INSERT
를 방지버전 관리: 데이터에 버전 번호를 두고, 현재 저장된 버전보다 낮은 버전의 데이터가 들어오면 무시
상태 저장소 활용: Redis나 DB에 처리된 메시지 ID를 저장하고, 메시지를 처리하기 전에 ID의 존재 여부를 먼저 확인하여 중복 실행 방지
Exactly-once(정확히 한 번 전송)
메시지가 유실되거나 중복되지 않고, 정확히 단 한 번만 처리됨을 보장하는 가장 강력한 수준의 신뢰성 수준이다.
Producer:
enable.idempotence=true
/transactional.id=<UNIQUE_ID>
설정enable.idempotence=true
로 설정하여 브로커로의 메시지 중복 전송 방지transactional.id
를 고유하고 안정적인 값으로 설정하여 트랜잭션을 활성화이를 통해 여러 토픽 파티션에 걸친 '읽기-처리-쓰기' 작업을 하나의 원자적 단위로 묶어줌
Consumer:
isolation.level=read_committed
설정컨슈머는 최종적으로 커밋(Commit)된 트랜잭션에 포함된 메시지만 읽도록 설정
만약 트랜잭션이 처리 도중 중단(Abort)되면, 해당 트랜잭션에 포함된 모든 메시지는 컨슈머에게 노출되지 않아 데이터 정합성 보장
위 설정과 트랜잭션이라는 두 가지 기능을 결합하여, Kafka는 프로듀서의 최초 전송부터 컨슈머의 최종 처리까지 모든 과정에서 메시지가 정확히 한 번만 처리되도록 보장할 수 있다.
Last updated
Was this helpful?