강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

--님의 프로필 이미지
--

작성한 질문수

[아파치 카프카 애플리케이션 프로그래밍] 개념부터 컨슈머, 프로듀서, 커넥트, 스트림즈까지!

리밸런스 리스너를 가진 컨슈머 애플리케이션

리밸런스 onPartitionRevoked이 필요한 상황

해결된 질문

작성

·

26

0

안녕하세요.

onPartitionRevoked() 메서드에 대한 아래 설명을 보고 몇 가지 의문이 생겨 질문드립니다.

"리밸런스가 시작되기 직전에 호출되는 메서드이다. 마지막으로 처리한 레코드를 기준으로 커밋을 하기 위해서는 리밸런스가 시작하기 직전에 커밋을 하면 되므로 onPartitionRevoked() 메서드에 커밋을 구현하여 처리할 수 있다."

  1. 수동 커밋 모드(manual commit)의 경우, "마지막으로 처리한 레코드를 기준으로 커밋"한다는 의미를 어떻게 이해해야 할까요?
    리밸런싱이 발생하더라도 이미 poll()로 받아온 레코드는 그대로 처리할 수 있으니, 레코드 처리 및 커밋은 정상적으로 동작하지 않을까요?
    그럼에도 불구하고 onPartitionRevoked()에서 커밋하지 않으면 '커밋을 구현하여 처리할 수 있다'는 어떤 의미인지 궁금합니다.

  2. 오토 커밋 모드(auto commit)의 경우에는 onPartitionRevoked()가 어떤 상황에서 필요하게 되는지도 잘 감이 오지 않습니다.
    이 경우에도 별도의 처리를 하지 않으면 유실이나 중복이 발생할 수 있다는 의미인지, 혹은 다른 목적이 있는지 궁금합니다.

     

답변 2

0

데브원영 DVWY님의 프로필 이미지
데브원영 DVWY
지식공유자

안녕하세요. 답변드립니다.

1) '마지막으로 처리한 레코드를 기준으로 커밋'

  • 수동 커밋 종류에 따라 poll()이 이전에 호출되더라도 커밋이 되지 않을 때가 있습니다. 예를 들자면 일장 시간마다 수동 커밋을 하는 구문을 작성한 것이 있을 수 있습니다.

  • 이런 경우, 리밸런싱이 발생할때 마지막으로 처리한 record의 offset을 기준으로 commit을 수행하지 않으면 예상치 못한 결과가 발생할 수 있습니다.

  • 그러므로, onPartitionRevoked()에서 그런한 상황에 처할 경우 커밋을 하는 로직을 해당 리스너에서 구현하는 것이 좋다는 의미입니다.

2) 오토커밋에서 언제 필요할지?

  • 컨슈머는 할당된 파티션을 기준으로 데이터를 처리하게 됩니다. 상황에 따라 onPartitionRevoked()에 컨슈머 처리에 따른 리소스의 할당 및 해제가 필요할 수 있습니다.

  • 예를 들어, consumer가 받은 record의 partition번호에 따라 {partition 번호}.txt 에 데이터를 저장하는 컨슈머 애플리케이션이 있다고 가정했을 때, 해당 파티션이 컨슈머에서 해제될 경우 리스너에서 file write flush & io close 와 같은 조치가 필요할 수 있습니다.

     

--님의 프로필 이미지
--
질문자

감사합니다. 이해가 됐습니다!


조금 다른 이야기지만, Kafka 컨슈머가 레코드를 처리한 뒤 오프셋을 커밋하기 전에 장애가 발생하면, 해당 레코드는 다시 처리되고, 이런 경우 레코드의 중복 처리는 피하기 어려워 보이는데요.

이처럼 중복 처리가 발생해도 실제 서비스에 문제가 없도록 만드는 것은 Kafka 자체의 책임이라기보다는, 서비스 레벨에서의 설계 책임이라고 이해해도 될까요?
Kafka를 처음 배울 때는 컨슈머가 "반드시 레코드를 한 번만 처리해야 한다"고 생각했지만, 현실적으로는 장애 등으로 인해 두 번 처리되는 경우를 고려한 방어적 설계가 필요하다는 생각이 듭니다.

이해한 바가 맞는지, 그리고 일반적으로는 어떻게 대응하는지 궁금합니다.

답변 감사합니다~!

데브원영 DVWY님의 프로필 이미지
데브원영 DVWY
지식공유자

이해가 되었다니 다행입니다!

좋은 추가 질문을 해주셨는데요. 카프카 컨슈머의 레코드 중복 처리는 사실, 카프카만의 설계 책임이 아닙니다. 일반적인 Rest API를 개발하실때도 되돌이켜보면, client -> server 에서 client가 server로 요청(request)를 날릴때 실패(timeout, 500 server error 등)이 난다면 재시도 또는 로깅을 통해 처리를 합니다. 카프카에서도 비슷한 전략을 사용하시면 됩니다.

카프카 컨슈머가 커밋을 하지 못하고 종료된다면 중복 처리가 될 가능성이 분명히 있습니다. 이런 경우를 제거하기 위해서는 컨슈머에서 중복 처리에 방어적인 설계를 처음부터 생각하시는 것이 가장 좋습니다. 관련해서 제가 발표한 영상이 있으니 참고하시면 좋겠습니다.

감사합니다.

--님의 프로필 이미지
--
질문자

감사합니다! 좋은 하루 보내세요~!

0

안녕하세요, 인프런 AI 인턴입니다.

  1. 수동 커밋 모드(manual commit) 에서는 “마지막으로 처리한 레코드를 기준으로 커밋”한다는 것은, 리밸런스가 발생하기 직전에 처리한 레코드의 오프셋(offset)을 안전하게 저장하는 것을 의미합니다. 리밸런싱 시 onPartitionRevoked()가 호출되는 이유는, 소비자가 소유한 파티션이 다른 소비자로 이전되기 직전 마지막 상태를 정확히 저장하기 위함입니다. 이 메서드에서 커밋을 하지 않게 되면, 리밸런싱으로 파티션이 다른 소비자로 옮겨졌을 때, 이미 처리된 레코드에 대한 오프셋 정보가 사라질 수 있습니다. 따라서 onPartitionRevoked()를 이용하여 마지막으로 처리된 오프셋을 커밋하여 데이터 손실을 방지할 수 있습니다.

  2. 오토 커밋 모드(auto commit) 의 경우, 카프카는 자동으로 특정 주기마다 오프셋을 커밋합니다. 그러나 리밸런싱과 같은 중요한 이벤트 전에 즉각적으로 커밋이 필요할 수 있습니다. onPartitionRevoked()는 주기적인 자동 커밋 외에도 중요한 시점에 오프셋을 확실히 저장하여 데이터를 더 안전하게 보장할 수 있습니다. 오토 커밋 모드에서도 onPartitionRevoked()를 적절히 사용하여 데이터 유실이나 중복 처리를 방지하는 것이 좋습니다.

참고로, 리밸런싱은 컨슈머 그룹 내의 컨슈머 세트를 최적화된 상태로 유지하기 위한 과정이며, 이에 따라 오프셋 관리가 중요합니다. Kafka 3.6 Documentation에서 리밸런싱에 관한 자세한 정보를 확인하실 수 있습니다.

--님의 프로필 이미지
--

작성한 질문수

질문하기