TIL

Kafka 동시에 같은 이벤트 들어오는 경우

하얀잔디 2025. 5. 25. 17:57

어떤 상황에서 같은 이벤트가 동시에 들어올까?

1. Upstream 시스템이 중복 전송할 때

  • 예: 서버 장애로 재전송 → Kafka에 동일 메시지 두 번 push됨
  • 예: 버튼 두 번 클릭 → API 두 번 호출 → Kafka 두 번 전송

2. 이벤트 발생 기준이 애매할 때

  • 예: 상태가 저장되기 전에 이벤트 발생 → 동일 내용 여러 번 발생
  • 예: 알림 대상 유저가 여러 명인데, 같은 알림ID로 반복 전송됨

3. 컨슈머가 빠르게 재시도할 때

  • 메시지 처리 실패 → offset을 커밋 안함 → Kafka는 같은 메시지를 재전송

 

 

 

대처법

 1. Idempotent 처리

"같은 메시지가 여러 번 들어와도 결과는 한 번만 발생하도록"

 
if (!alreadyProcessed(event.getId())) { saveToDb(event); markAsProcessed(event.getId()); }
  • eventId 기준으로 Redis나 DB에서 처리 여부 캐싱
  • Redis SETNX(set if not exists)로 처리 중복 방지 가능

 2. Kafka 메시지 키를 설정 - > 순서보장

 
 
ProducerRecord("topic", key = event.id, value = event)
  • 같은 key는 같은 파티션에 들어가고, 순서 보장
  • 컨슈머에서 "같은 이벤트"가 순서 보장되는 상황이면 중복 처리도 더 쉽다

 

  • Key 없이 아무 데나 보내면 → 3개의 알림이 서로 다른 파티션 → 동시에 처리됨 → 중복 처리될 가능성 높음
  • Key를 주면 → 모두 같은 파티션 → Kafka가 순서대로 보냄 → 하나씩 처리되므로 우리가 중복 체크하기 쉬움

 


3. 중복 방지용 락 사용 (Redis 등)

 
val locked = redisson.tryLock("event:${event.id}", 3, 10, TimeUnit.SECONDS)
if (locked)
{
        try { process(event) }
       finally
         { lock.unlock()}
}
  • 여러 컨슈머 인스턴스가 있을 때 하나만 처리하게 만듦
  • 실시간 동시성 문제에서 꽤 효과적

 4. DB unique 제약 조건 활용

  • 이벤트 결과를 저장할 때 중복 저장 방지용으로 PK 또는 UNIQUE 제약 설정
 
CREATE UNIQUE INDEX ux_event_id ON processed_events(event_id);
  • 중복이 들어와도 DB가 차단

💡 예시

알림 센터에서 같은 alarmId=123이 3번 연속 들어온 경우

  • Kafka 컨슈머에서는 Redis에 SETNX("alarm:123") 시도
  • 성공 시 → DB 저장 + 사용자에게 푸시 전송
  • 실패 시 → 이미 처리 중이거나 완료된 알림이므로 무시

'TIL' 카테고리의 다른 글

소켓에서 레디스를 왜 쓸까?  (0) 2025.06.29
istio란?  (0) 2025.05.29
Spring 트랜잭션 RollbackFor  (0) 2025.05.22
Spring 트랜잭션 전파 레벨  (0) 2025.05.22
Flutter 앱 아이콘 / 스플래시 이미지 적용법  (0) 2025.05.21