Kafka로 주문 이벤트를 처리하는 컨슈머를 돌리고 있는데, 가끔 같은 주문이 두 번 처리되는 문제가 있습니다. 로그 보니까 컨슈머가 메시지를 받아서 로직을 다 태우고 오프셋을 커밋하기 직전에 인스턴스가 죽으면, 재시작했을 때 그 메시지를 다시 읽어서 또 처리하더라고요. 정확히 이해하려고 문서를 파는 중입니다.
제가 파악한 바로는 기본 세팅이 at-least-once라서 이게 정상 동작이라고 하네요. 처리를 먼저 하고 오프셋을 나중에 커밋하니까, 그 사이에 크래시가 나면 재처리가 발생해서 중복이 생긴다. 순서를 뒤집어서 오프셋을 먼저 커밋하면 이번엔 크래시 시 메시지를 잃어버리는 at-most-once가 되고요.
records = consumer.poll();
for (r : records) { process(r); } // 여기까지 하고
consumer.commitSync(); // 이 직전에 죽으면 재처리
exactly-once도 있다고 들었는데 멱등 프로듀서에 트랜잭셔널 컨슈머까지 붙여야 하고 스트림 쪽에서나 제대로 쓰는 거라 비용이 크다고 하더라고요. 그래서 결론은 at-least-once로 전달은 보장하되 소비하는 쪽에서 멱등하게 짜는 게 실무 정석인지 궁금합니다. 소비 측 멱등 처리는 보통 처리한 메시지 ID를 어디에 기록해두고 중복이면 스킵하는 식으로 하나요? 다들 어떻게 하시는지 듣고 싶습니다.