Kafka Message Delivery Semantics
안녕하세요~
우리는 저번시간에 kafka producer 와 consumer 에 대해서 알아보았습니다.
https://huisam.tistory.com/entry/kafka-consumer?category=849126
https://huisam.tistory.com/entry/kafka-producer?category=849126
2가지 구성요소를 공부하다 보면, 여러 의문들이 생길 테지만,
가장 기본적인 의문은 그러면 도대체 어떻게 메세지가 전달되고, 어떤 전략으로 메세지를 전송하는 것이지?
에 대한 의문이 생길 수가 있습니다.
오늘은 이 2가지 구성요소를 종합하여, Kafka 가 어떤 전략으로 메세지를 전송하는지에 대해 알아볼게요
흔히 Kafka Message Delivery Semantics 이라고 합니다.
Message Delivery Semantics
어떤 메세지 전송 전략이 있을까요?
먼저 용어에 대해서 한번 파헤쳐봅시다
용어 | 설명 |
No gurantee | 메세지 전송에 대해 보장하지 않는다. Consumer 는 Producer 가 보낸 메세지가 유실되거나 한번 또는 여러번 동일한 메세지를 처리할 수 있다 |
At monce once | 메세지 전송에 대해 최선으로 1번 처리할 것을 보장한다. 단 이때 중복가능성을 피하기 위해 메세지가 전송되지 않을 수도 있다. |
At least once | 메세지 전송에 대해 최소 1번 처리할 것을 보장한다. Consumer는 1번 또는 여러번 메세지를 처리할 수 있다 |
Exactly once | 메세지 전송에 대해 '정확히' 1번 처리할 것을 보장한다. |
흔히들 Kafka Streams 를 먼저 경험하신 개발자라면,
원래부터 kafka는 'Exactly Once 아닌가요?' 이렇게 생각할 수 있지만 아닙니다.
이를 이해하기 위해서는 Producer 와 Consumer 측에서 메세지를 어떻게 전송하는지 알아야 합니다.
Producer Message Semantic
Producer 측에서 메세지를 어떻게 전송하는지 봐볼게요
Kafka Broker 에게 메세지 토픽을 전달하고, offset 을 저장하는 storage 에 어떻게 저장할 것인지에 따라
각각의 정책들은 나뉘어지게 됩니다.
사실은 그림에서는 offset storage 기반으로 되어 있다고는 하지만,
엄밀히 말씀드리면 Producer 와 Broker의 ack 통신 과정과 연관이 있습니다
At most once 는 Offset Storage 에 저장을 하지만, Broker 에게 전달하는 과정에서 누락이 될 수 있고,
At least once 는 Broker 에게 전달하는 과정을 보장하지만, Offset Storage 에 저장하는 과정에서 중복 체크에 대한 유실이 생길 수 있습니다.
No gurantee 는 볼 필요가 없으니 생략 ㅎㅎ
그렇다면 exatctly once 는 어떻게 동작하게 될까요?
Exactly Once 는 바로 2가지 행위(Broker 전달 + Offset Storage 저장)를 Atomic 하게 보장하는 것을 의미합니다.
그러면 어떻게 해야 각각의 메세지 전송 전략을 선택할 수 있을지 궁금하겠죠?
전략 | 방법 |
At most once | Producer 가 재시도 전략을 허용하지 아니하되, 정확하게 한번 전달하는 것을 보장하게 합니다. - 아직까지 저는 해당 전략으로 kafka 를 운영해본적은 없어서 모르겠습니다. |
At least once | - Producer 의 설정을 acks = all 로 설정합니다. acks = all 설정은 Leader 가 Follower 들에게 토픽을 잘 전송하였는지 체크하는 option 입니다. |
Exactly once | - Producer 의 설정을 acks = all 로 설정합니다. - enable.idempotence = true 로 설정합니다. idempotence 설정은 Broker 에게 ProducerID(PID) 를 전송하여 중복체크를 할 수 있게 전송하게 됩니다. |
Producer 의 ack 설정과 idempotence 설정은 이전 게시글을 참고해주세요 :)
Consumer Message Semantics
Producer 의 메세지 전송 의미론만 봐도 참 어렵죠.?
아직 끝난게 아니랍니다 ㅎㅎ Consumer 쪽은 조금 더 어렵습니다.
우선 간단하게 그림을 통해 먼저 이해를 도와드리도록 하겠습니다 :)
Consumer 의 동작원리는 아주 간단합니다.
- Consumer 가 마지막으로 기억하는 Offset 으로 부터 메세지를 읽습니다.
- Application 에게 읽은 메세지를 전송하여 Processing 합니다.
- Processing 이 완료되면 메세지를 Offset 에 commit 합니다
이렇게 한 cycle 이 지나면 Consumer 가 메세지를 consume 했다고 볼 수 있습니다.
기본적으로는 메세지를 Application 에게 전송한 뒤에 commit 하는 전략(At least once) 를 따르게 됩니다.
그렇다면 어떻게 하면 Exactly Once 전략을 취할 수 있을까요?
결론부터 말씀드리면 Application 단에서 멱등성을 보장하는 방법 입니다.
그 이유에 대해서 왜 그런지 차근차근히 알아보도록 하겠습니다.
Consumer 가 메세지를 읽고, offset 을 commit 하는 2가지 방법이 있습니다.
Property | Description |
enable.auto.commit = true | 일정 주기(auto.commit.interval.ms, default 5초)마다 poll 한 record 의 offset 을 commit 하는 전략 |
enable.auto.commit = false | application 단에서 수동으로 commit 하는 전략 |
auto.commit = true 의 경우에는 자동으로 commit 하기 때문에 아래와 같은 메세지 유실이 발생할 수 있어요
auto commit 정책 덕분에 application processing 에 지연이 생겨 fail 이 된다면,
offset 은 commit 했지만, 메세지에 대한 비즈니스는 처리하지 못한 것이죠.
이 전략은 kafka 가 At most once 를 따르기 때문입니다.
auto.commit = false 의 경우에는 수동으로 commit 을 하기 때문에 메세지를 중복처리하는 상황이 발생할 수 있어요
이번에는 Application 비즈니스를 먼저 수행하고, offset 을 commit 하기 때문에 발생하는 상황입니다.
Application 단 비즈니스는 성공했지만, offset 을 commit 하는 과정에서 네트워크 이슈로 실패합니다
Consumer 는 다음번에 같은 offset 으로 메세지를 읽기 때문에, 메세지에 대해 중복으로 비즈니스를 수행하게 되는 것이죠
이 결과는 kafka 가 At least once 전략을 따르기 때문입니다.
따라서 Consumer 가 commit 을 우선시 할 것이냐 Processing 을 우선시 할 것이냐 를 선택해도 Exactly once 를 보장할 수는 없습니다.
오히려 Commit 을 우선시 하는 경우에는 2단계 Commit 과 같은 안전장치가 필요하며, kafka transaction 을 사용하기 때문에 성능에 영향을 줄 수도 있는 부분이죠.
그래서 대게는 별도의 메세지 처리 비즈니스로 해결하게 됩니다.
Consumer 의 비동기 commit 인 auto.commit = true 를 활성화하고, 메세지에 대한 Consume 기록을 DB 로 하는 방향입니다.
그렇게 되면, Application 에서 Processing Fail 이 발생해도 안전하게 재시도가 가능하기 때문입니다.
Application Processing 단계에 Kafka Consumer 가 exactly once 를 수행하는데에 있어서 방해가 되지 않도록 차단하는 것이죠
Kafka streams 에서는 exactly once 에 대한 기능 지원이 가능하나, 일반적으로 spring-kafka 에서는 지원하지 않습니다.
Kafka streams 에서 어떻게 exactly once 를 지원하는지는 아래링크를 참고하시기 바래요!
https://www.confluent.io/blog/enabling-exactly-once-kafka-streams/
정리하며
그래서 많은 내용을 정리하였지만, 쉽게 요약하자면..!
- Message Semantics 를 결정하게 되는 요소는 Producer, Consumer 각각의 측면에서 바라보아야 한다.
- Kafka 는 Default 세팅을 사용한다면 Producer 측면에서는 At Least Once, Consumer 측면에서는 At Most Once 전략입니다.
- Exactly once 전략을 사용하기 위해서는 Producer 에는 idempotence 와 ack 옵션을, Consumer 에는 메세지 consume 기록을 위한 DB 를 활용해야 한다.
혹여나 오타나 제가 잘못 이해한게 있다면, 언제든 댓글 달아주세요!
감사합니다 :)
참고 링크
Processing gurantees in Kafka
Exactly-Once Semantics are possible
Apache Kafka: Semantics
'Developer > Stream' 카테고리의 다른 글
Apache Kafka Producer - Producer Deep Dive 를 해보자 (4) | 2022.04.30 |
---|---|
Apache Kafka Consumer - Consumer Deep Dive 하기 HeartBeat & Rebalancing 이란? (0) | 2021.08.14 |
Apache Kafka - 메세지 브로커에 대해 알아보자 (0) | 2021.03.01 |