인프런 커뮤니티 질문&답변
컨슈머 이벤트 중복 처리
해결된 질문
작성
·
52
·
수정됨
0
안녕하세요! 자주 질문드리는데 정성껏 답변해주셔서 감사합니다!
동일한 이벤트가 중복 전송될 가능성이 있기 때문에 article-read 서비스에 이벤트 id를 통한 중복 처리 로직을 추가 하려고합니다.
article-read 는 redis를 사용하고 있기 때문에 redis에 이벤트 id를 저장해 해결하려고했습니다.
예를 들어 article-read가 이벤트를 받았을때
redis 에서 이벤트 id 확인
동일한 이벤트 id가 저장돼 있으면 추가 처리 안하고 message ack
redis 에서 이벤트 id 확인
동일한 이벤트 저장된게 없으면 서비스 로직 수행
서비스 로직 결과 redis 업데이트
처리 완료한 이벤트 id redis 저장
이런식으로 진행하려 했으나 만약 어떠한 문제로 인해
서비스 로직 결과 redis 업데이트 ( 성공 )
처리 완료한 이벤트 id redis 저장 ( 실패 )
하게되면 이벤트 처리는 성공했지만 처리된 이벤트 저장에는 실패해 추후에 중복 처리가 발생할 가능성이 생길 것 같습니다.
이러한 문제 해결을 위해
서비스 로직 결과 redis 업데이트
처리 완료한 이벤트 id redis 저장
두 작업을 하나의 트랜잭션으로 묶어 처리하려고했지만 rdb 와 동작이 다르기 때문에 (롤백 기능 제공 안함 등) 적절한 방법인지 판단이 안서는 상태네요
혹시 article-read에 이벤트 중복 처리를 한다고 하면 어떻게 구현이 가능할지 여쭤보고싶습니다
답변 2
0
jhkim593님, 안녕하세요!
직접 능동적으로 고민하며 궁금한 점 해소해 나가는 것 너무 좋은 자세입니다!
(요즘 평일에 시간이 없어서 답변이 늦어 양해 바랍니다..!)
혹시 article-read에 이벤트 중복 처리를 한다고 하면 어떻게 구현이 가능할지 여쭤보고싶습니다
정확히 어떠한 로직에 대해서 중복 처리를 해야하는지 알면 좋을 것 같은데요,
일단 중복을 반드시 막아야 하는지부터 고민해볼 것 같습니다.
컨슈머의 로직 처리를 멱등하게 설계한다면, 동일한 이벤트를 여러번 처리하더라도 문제될 부분은 없습니다.
또는 멱등하지 않더라도, 중복 이벤트가 발생하더라도 감수할 있는 상황도 있습니다.
예를 들어, 100% 정확할 필요가 없는 통계성 데이터 작업 같은 것들이 있겠네요.
중복을 완벽하게 제한하는건 비용이 들기 때문에, 위처럼 먼저 고민해보시는 것도 좋습니다.
article-read의 consumer 로직도 멱등하게 설계되어 있어서 중복 처리되어도 크게 문제될 부분은 없습니다.
만약 중복을 반드시 제한해야 한다면,
말씀하신대로 이벤트 ID를 활용할 수도 있고, 이벤트와 1:1 매핑되는 어떠한 유니크 식별자를 사용할 수도 있습니다.
그리고 트랜잭션을 지원하지 않고 유니크를 완벽하게 보장할 수 없는 Redis가 적절한 해결 도구인지 고민해보면 좋을 것 같네요.
RDB의 유니크 인덱스와 트랜잭션을 활용하면서 로직을 처리하는게, 중복 방지에 대해 더욱 안전한 해결책이라고 생각됩니다.
다른 방법으로는, 말씀하신 방안으로 최소한의 중복 방지를 취하되, 후에 모니터링하여 중복을 감지하고 롤백 시키는 것도 하나의 방법입니다.
0
안녕하세요, 인프런 AI 인턴입니다. 김진현님.
Kafka와 같은 메시지 브로커를 사용할 때, 이벤트의 중복 전송은 예상 가능한 문제입니다. 이를 방지하기 위한 방법 중 하나는 이벤트의 ID를 기반으로 중복 처리를 구현하는 것입니다.
Redis를 사용한 중복 처리에 대한 전략을 아래와 같이 정리해보겠습니다.
기존 계획의 문제점
제시하신 로직에서는 이벤트 처리 후 ID 저장이 실패할 경우 중복 처리가 되지 않을 수 있다는데, 이는 일관성 문제로 이어질 수 있습니다.
해결 방안
중복 처리 로직 강화:
이벤트를 처리할 때는 두 가지 작업, 즉 “서비스 로직 수행”과 “이벤트 ID 저장” 모두 실패할 경우 전체 작업을 무효화해야 합니다.원자적 작업 활용:
Redis의 멀티 명령어 트랜잭션을 활용하여 “서비스 로직 결과 업데이트”와 “이벤트 ID 저장”을 하나의 원자적 명령으로 묶을 수 있습니다. 이는 Redis의MULTI와EXEC명령어를 사용하여 구현할 수 있습니다.분산 락 이용:
중복 처리를 위해 분산 락을 사용할 수 있습니다. 예를 들어, 처리 중인 이벤트에 대해 락을 걸고, 처리가 완료될 때까지 다른 인스턴스에서 동일한 이벤트를 처리하지 못하게 할 수 있습니다. Redis의SETNX명령어를 이용하면 쉽게 구현할 수 있습니다.2단계 커밋 시뮬레이션:
만일 Redis와 RDBMS 간의 일관성을 높이고 싶다면 2단계 커밋을 시뮬레이션하는 방법도 고려해 볼 수 있습니다. 이는 일부 실패 시 복구 롤백 로직을 미리 구현해 두어 실패에 대응하는 것을 의미합니다.복제와 확인 전략:
이벤트 ID 저장이 실패했을 경우를 대비하여, 이벤트 ID를 다른 저장소에도 복제하는 방식으로 실패 검증을 강화할 수 있습니다.
이런 접근법들은 시스템의 요구사항에 따라 다양하게 조정될 수 있습니다. 아래 유사한 문제 및 해결 방법을 다룬 링크도 참고해 보세요:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





