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 — 제외