DEVELOPMENT NOTE / Ask Wiki

Transactional Outbox로 유령 인덱스 방지

문제

  • 트랜잭션 안에서 DB 저장과 검색 인덱스 반영을 동시에 수행한 초기 구조
  • 중간 예외 시 DB만 롤백되고 인덱스에 남은 유령 청크 2건
  • 검색 인덱스가 DB 트랜잭션에 참여하지 못하는 원자성 경계

해결

  • 같은 DB 트랜잭션에 index_outbox 이벤트 저장
  • 별도 polling relay의 PENDING 조회 → 인덱스 반영 → PROCESSED 마킹
  • 반영 후 마킹 순서와 chunkId 기준 멱등 처리로 at-least-once 재시도 보장

검증 방법

  • 개선 전 흐름에서는 Elasticsearch 반영 직후 예외를 강제로 발생시켜 DB 롤백 뒤에도 남는 chunkId를 집계
  • Outbox 적용 후에는 relay를 중단한 상태로 문서를 저장해 PENDING 이벤트를 만든 뒤, relay 재시작 후 PROCESSED 전환과 색인 반영을 대조
  • 같은 이벤트를 다시 처리해도 chunkId 기준 upsert로 검색 문서 수가 늘지 않는지 확인

검증 결과

항목결과
롤백 후 유령 인덱스2건 → 0건
relay 재시작PENDING 이벤트 처리 후 인덱스 반영
평균 반영 지연126.7ms
최대 반영 지연211ms
  • 유령 인덱스 수치는 2개 청크를 가진 문서 1건에서 강제로 롤백시킨 단일 재현 결과다.
  • relay 재시작 검증은 PENDING 이벤트의 처리 완료 여부를 확인했으며, 대량 이벤트의 고유 ID 집합을 대조한 유실률 측정은 아니다.

한계

  • 폴링 주기에 따른 최종 일관성과 반영 지연
  • DB에서 재구성 가능한 파생 데이터라는 특성에 맞춘 Kafka — 제외