Kafka에서의 Exactly Once Delivery 구현
메시지 시스템을 사용하다 보면 메시지의 전달 보장 방식에 대해 고려해야 합니다. 일반적으로 다음 세 가지 전달 방식이 있습니다.
- At Least Once Delivery: 메시지가 최소 한 번 전달됩니다. 중복 메시지가 발생할 수 있습니다.
- At Most Once Delivery: 메시지가 최대 한 번 전달됩니다. 메시지가 손실될 수 있습니다.
- Exactly Once Delivery: 메시지가 정확히 한 번 전달됩니다. 중복이나 손실이 없습니다.
Kafka를 사용할 때, 메시지의 정확한 전달을 보장하는 것은 중요한 이슈입니다. 특히 Consumer 측에서 메시지를 처리하는 과정에서 중복이나 손실 없이 메시지를 정확히 한 번씩 처리하도록 구현하는 방법을 알아보겠습니다.
Kafka의 기본 전달 보장 방식
Kafka는 기본적으로 At Least Once Delivery를 제공합니다. 이는 메시지가 최소 한 번 소비자에게 전달됨을 의미하며, 네트워크 장애나 처리 오류로 인해 중복 메시지가 발생할 수 있습니다.
Exactly Once Delivery를 위한 설정과 구현
1. Idempotent Producer 설정
Producer 측에서 동일한 메시지를 여러 번 전송하더라도 중복 없이 처리되도록 설정할 수 있습니다.
enable.idempotence 옵션을 true로 설정합니다.
Properties props = new Properties(); props.put("enable.idempotence", true);
이 설정을 통해 프로듀서는 메시지 전송 시 고유한 PID(Producer ID)와 시퀀스 넘버를 사용하여 중복 전송을 방지합니다.
2. Transactions 활용
Kafka는 트랜잭션 기능을 통해 메시지의 원자성을 보장합니다.
트랜잭션 초기화
producer.initTransactions();
트랜잭션 시작과 종료
try { producer.beginTransaction(); // 메시지 전송 로직 producer.send(record); producer.commitTransaction(); } catch (Exception e) { producer.abortTransaction(); }
3. Consumer 측의 처리 보장
Consumer에서 Exactly Once Semantics(EOS)를 구현하기 위해서는 다음을 고려해야 합니다.
Kafka Streams API 사용
Kafka Streams는 EOS를 기본적으로 지원하며, 상태 저장 프로세싱에 유용합니다.
오프셋 커밋 관리
수동으로 오프셋을 커밋하여 메시지 처리와 오프셋 관리의 원자성을 보장합니다.
consumer.commitSync();
데이터베이스 트랜잭션과 연계
메시지 처리 결과를 데이터베이스에 저장할 때, Kafka 오프셋 커밋과 데이터베이스 트랜잭션을 연계하여 원자성을 확보합니다.