자기개발/개발이야기

Kafka의 Auto Commit 에서 Auto는 당신이 생각하는 Auto가 아닐 수 있다.

환경설정을 할 때 auto라는 키워드가 나오면 작업자는 날먹을 꿈꾸며 행복해지는 한 편, 이 auto가 어디까지 자동으로 해주고 어디까지는 안해주는지 공포에 떨며 작업을 하게 된다.

나에게 kafka의 auto.commit이 그런 느낌이었다.

Kafka의 auto란 따로 commit하라고 요청 안해도 일정 시간 간격마다 알아서 commit 이라는 뜻의 auto이다.

https://kafka.apache.org/23/javadoc/org/apache/kafka/clients/consumer/KafkaConsumer.html

Setting enable.auto.commit means that offsets are committed automatically with a frequency controlled by the config auto.commit.interval.ms.

그러면 일정 시간마다 알아서 commit해주겠구나!하고 넘어가면 안되는게, 사실 kafka는 poll로 땡길때마다 내가 마지막에 소비한 offset을 전달한 후 받아온다는 사실을 기억하자.

https://kafka.apache.org/23/javadoc/org/apache/kafka/clients/consumer/KafkaConsumer.html#poll-java.time.Duration-

On each poll, consumer will try to use the last consumed offset as the starting offset and fetch sequentially. The last consumed offset can be manually set through seek(TopicPartition, long) or automatically set as the last committed offset for the subscribed list of partitions

그러니 auto commit을 하면 poll을 호출 안해도 offset을 일정 시간마다 commit해주는 것이라 표현해도 좋을 것이다.


이 Auto Commit에 대해 검색해보면 다들 중복/유실문제를 이야기하고 있는걸 볼 수 있다.
이는 일정 시간이 지나면 내가 메시지를 처리했던 처리못했던 알아서 offset을 갱신하기 때문이다.

에러가 발생했을 때 auto commit을 했나 안했나에 따라서 중복이기도 하고 유실이기도 하다.

  • 유실

    • 내가 poll을 통해서 가져온 message들을 다 처리못한 상태로 commit
      • auto.commit.interval.ms 가 지난 상황
    • 그 상태에서 내가 남은 메시지를 처리 못한 채로 에러 발생 (로직오류, 인스턴스 다운 등등...)
    • 이미 처리못한 message를 포함해 offset이 갱신되었기에 다음 poll때 처리못한 메시지를 가져올 수 없음
  • 중복

    • 내가 poll을 통해서 가져온 message들을 다 처리 못한 상태로 commit 타이밍도 아직 안됨
      • auto.commit.interval.ms 가 아직 지나지 않은 상황
    • 그 상태에서 내가 commit을 못한 채로 에러 발생 (로직오류, 인스턴스 다운 등등...)
      • 가져온 메시지에 대해 commit이 안된 상황
    • 가져온 메시지에 대한 offset이 갱신되지 못했기에 다음 poll때 처리한 메시지를 포함해가져옴

    메시지 처리가 아닌 일정 시간이 지났나 기준으로 offset을 commit 하기에 생기는 문제다.

생각보다 멍청하게 자동으로 해준다는 사실을 알고, 이런 문제가 일어나면 안되는 작업은 auto commit으로 하면 안된다.

(그래서 보통 작업은 이 작업이 자동 세팅 외에 다른 처리를 해 줘야 할까?로 생각하는데, kafka는 이 작업을 자동 세팅으로 해도 문제가 안될까?라는 생각흐름으로 작업을 해야하지 않을까 싶다. 자동으로 작업해도 되는게 생각보다 적을 것 같다)