Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Kafka 에서 Exactly once 를 지원한다고 들었고 정확히 어떤 기능인지 찾아보았다.

결론적으론 생각보다 많이 달랐다.

내가 생각하는 Exactly once 란 메세지 A 를 정확히 1번 publish -> 컨슈머가 정확히 1번 consume 어떤 메세지가 한 번 소비되는 것 인데, 그게 아닌 메세지 A offset commit + topic B 에 메세지 publish 와 같이 카프카 내부 트랜젝션을 하나로 묶는 기능이였다. 그래서 예를 들어 message A 처리 결과를 topic B, C 에 쓴다라고 했을 떄 message 를 원자단위로 잘 묶어주는 기능이다.

그래서 Exactly Once 메세지를 정확히 한 번 소비를 만족하기 위해선 최종적으로 옵션딸깍으로 되는게 아닌 아래와 같이 설계해야한다.

  1. idempotent 옵션(redis stream 의 경우 xadd 에 옵션이 있다.)로 메세지 중복 publishing 을 막아야하고
  2. consume 시 비즈니스 로직에 따라 멱등을 보장해야한다.
    • 비즈니스 로직이 DB 쓰기작업의 경우 로직수행 + event-id unique key insert tx 해놓으면 이후 동일 event-id 으로 로직수행 시 key validation 에러나서 중복소비를 막아준다. 트랜젝션 롤백일어나면 뭐 없던일이 되니까 재수행하면 된다.
    • 마찬가지 외부 API 호출이면 DB 에 event-id 랑 같이 SENDING, SUCCESS, FAILED, UNKNOWN 로 개별 commit 해서 DB 저장. 네트워크 연결유실이 흔하니까 polling batch 해서 보정처리한다.

이후 로직 완료하고 메세지 ACK commit 하면 된다.