강의

멘토링

로드맵

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

rlapwl님의 프로필 이미지
rlapwl

작성한 질문수

스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판

카프카 메시지 순서 관련 문의

해결된 질문

작성

·

13

0

안녕하세요 강사님!

카프카를 사용하면서 궁금한 점이 있어서요~

 

예를 들어 주문 시스템을 구현한다고 하면요.

주문에 대해 상태가 계속 바뀌어 해당 이벤트를 받을 수 있도록 카프카를 붙이려고해요.

consumer가 동일한 주문 id에 대해 상태 업데이트를 해야 하니, producer가 순서 보장되도록 카프카 key도 동일하게 셋팅하면 consumer는 순서대로 status를 제대로 update 하는데요.

 

만약 producer가 메시지 발행을 비동기적으로 진행하도록 구현했다고 하면,

무언가 이슈로 주문 생성 -> 주문 취소 순이 아닌 주문 취소 -> 주문 생성 순으로 발행되었다면

consumer 입장에서 메시지 순서가 제대로 들어왔음을 어떻게 인지할 수 있을까요..?

 

이런 상황은 발생하지 않을까요..? ㅎㅎ

답변 2

0

쿠케님의 프로필 이미지
쿠케
지식공유자

rlapwl님, 안녕하세요!

 

순서에 대해서 완벽하게 보장하는 것은 쉬운 문제는 아닙니다.

주문 id를 파티션 키로 지정한다고 하더라도, 순서가 변경될 수 있는 상황은 분명 있습니다.

말씀하신대로 비동기 상황에서는 producer가 순서를 바꿔서 보낼 수도 있고,

컨슈머가 모종의 이유로 실패하여 별도의 재처리 토픽에서 retry를 시도하다가 순서가 바뀔 수도 있고,

이벤트 전송을 동시에 처리하는 설정일 수도 있고(max.in.flight.requests.per.connection),

파티션 수를 늘리는 과정에는 파티션 키는 동일하더라도 새로운 이벤트가 다른 파티션으로 이벤트가 적재될 수도 있는 등..

이러한 상황을 해결하기 위해서는 Producer가 발행하는 이벤트에 대해 넘버링을 할 수도 있을 것 같고요(컨슈머는 반드시 마지막 시퀀스와 최신 시퀀스에 대해 diff=+1인 이벤트만 정상 이벤트로 간주),

논리적인 관계(주문 완료 상태가 아닌데, 주문 취소 상태 이벤트가 먼저 수신될 수는 없음)를 이용할 수도 있을 것 같습니다.

또는, 이벤트를 컨슈머에서 append-only로 저장하다가 모두 수신 됐을 만한 충분한 시간을 대기한 후에, 순차적으로 처리하는 것도 하나의 방법일 것 같습니다.

 

논리적인 관계가 복잡하지 않고 명확하고 간단히 정의되어있다면 해당 방법만을 채택할 것 같고,

더욱 복잡한 상황이라면 넘버링 정책으로 컨슈머가 순서 변경도 감지하고,

평시에는 실시간으로 즉시 처리하다가 문제가 발생한 데이터에 대해서 알람 또는 모니터링 후에 수동 처리 및 관련 원인 개선을 해나갈 것 같습니다.

파티션 수를 늘리는 과정에 대한 문제는, 일시적으로 이벤트를 모두 소진한 뒤에 잠시 중단 상태로 만들 수도 있고요.(시스템 점검과 같은 상황에 처리) 파티션 id를 고정으로 지정할 수도 있을 것 같습니다.

사실 시스템 장애 상황에는 아키텍처에 따라 순서 변경 여지에 대해서 완벽하게 방지할 수는 없으므로, 여러 가지 방법을 복합적으로 고려해봐야할 것 같습니다!

(참고 - 예전에 유사한 질문이 있었네요.)

0

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

카프카를 사용하면서 주문 상태를 관리할 때, 메시지의 순서 보장은 중요한 이슈 중 하나입니다. 카프카는 각 파티션 내에서 메시지의 순서를 보장하지만, 프로듀서가 비동기적으로 메시지를 발행할 때 각 메시지가 언제 처리될지 예측하기 어려울 수 있습니다.

카프카에서 메시지 순서 보장

  1. 키를 활용한 파티션 관리:

    • 프로듀서는 동일한 주문 ID에 대해 항상 동일한 파티션으로 메시지를 발행해야 합니다. 이를 위해 메시지의 키를 주문 ID로 설정하여 같은 파티션에 기록되도록 합니다. 이렇게 하면 파티션 내에서는 메시지 순서가 보장됩니다.
  2. 타임스템프 및 시퀀스 번호 활용:

    • 각 메시지에 이벤트의 발생 시간을 나타내는 타임스탬프를 추가하거나, 순차적인 시퀀스 번호를 부여하여 컨슈머가 메시지의 순서를 확인할 수 있게 합니다. 이를 통해 컨슈머가 과거 시점의 이벤트를 무시하거나, 별도의 처리 로직을 추가할 수 있습니다.
  3. 트랜잭션 사용:

    • 가능하다면 카프카의 트랜잭션 기능을 사용하여 한꺼번에 여러 메시지를 프로듀서의 트랜잭션 단위로 묶어 보내고, 성공적으로 수행된 트랜잭션만을 커밋하는 방식으로 관리할 수 있습니다. 이 방법은 메시지를 보낼 때의 일관성 문제를 감소시킬 수 있습니다.

발생 가능한 문제 해결

순서가 어긋나는 상황은 발생하지 않을 수 없다 보니, 처리 로직에서 이를 감안하여 작성해야 합니다. 특정 이벤트에 따라 다른 이벤트가 처리되어야 하는 경우, 위에서 제시한 방법들을 사용하여 컨슈머 로직을 구현해 보시는 것이 좋습니다.

비슷한 주제에 관한 유사한 답변을 참고하면 이해하는데 도움이 될 수 있습니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

rlapwl님의 프로필 이미지
rlapwl

작성한 질문수

질문하기