자동입금 배치 무한 재처리와 알림 폭탄 수정기
목차
증상
새벽에 알림 채널이 폭발했음. 자동입금 처리 배치가 같은 건을 계속 재처리하면서 처리 완료 알림을 수백 건씩 쏘는 중이었음.
확인해보니 두 가지 문제가 겹쳐있었음.
- 기동 시 리셋 로직이 PROCESSING 상태인 큐를 전부 PENDING 으로 되돌리고 있었음
- 처리 완료 직전 잠깐 PROCESSING 으로 머무는 건도 같이 리셋됨
- 그게 다시 큐로 들어가 또 처리되고, 또 알림이 나감
원인
배치가 비정상 종료될 때 PROCESSING 상태로 매달려 있는 항목을 복구하려고 기동 리셋을 넣어둔 거였음. 의도는 좋았는데 조건이 너무 헐거웠음.
-- 기존 (문제)
UPDATE queue
SET status = 'PENDING'
WHERE status = 'PROCESSING'
워커가 여러 개 떠 있는 환경에서는, 한 워커가 기동되면 다른 워커가 정상 처리 중인 건까지 강제로 PENDING 으로 돌려버리는 꼴. 그러니 처리 → 리셋 → 재처리 → 리셋 무한루프.
수정
리셋 대상을 "오래 매달려 있는 것" 으로 한정함.
UPDATE queue
SET status = 'PENDING'
WHERE status = 'PROCESSING'
AND updated_at < NOW() - INTERVAL 10 MINUTE
10분 이상 진행이 없으면 죽은 워커가 잡고 있던 것으로 보고 회수. 정상 처리 중인 건은 건드리지 않음.
알림 폭탄은 별도로 처리. 큐에 발송 플래그 컬럼을 추가해서 이미 알림 이력이 있으면 재발송하지 않게 함. 어떤 이유로든 큐가 다시 돌더라도 알림은 한 번만.
배운 것
| 항목 | 교훈 |
|---|---|
| 기동 리셋 | 시간 조건 없으면 무차별 회수 → 멀쩡한 작업도 풀림 |
| 알림 발송 | 처리 동작과 알림 발송을 분리해야 멱등이 됨 |
| 루프 가드 | 같은 큐 ID 가 N번 이상 재처리되면 차단하는 가드 필요 |
기동 리셋 같은 보호 로직은 안전망인데, 조건을 헐겁게 짜면 오히려 사고를 키움. "언제 회수할지"를 명확히 정의하지 않은 게 근본 원인이었음. 알림도 결국 멱등성 문제였고, 처리 로직과 부수효과(알림)는 분리해야 한다는 걸 또 배움. 다음.
댓글 0
첫 댓글 달아줘.