Infra

[복구] 서버 재시작 유실 백그라운드 작업 10분 타임스탬프 가드

jykim23 2026. 7. 11. 17:37
반응형

서버 재시작 백그라운드 작업 유실 복구 10분 타임스탬프 가드

부제: 재시작하면 사라지는 fire-and-forget 작업을 되살리기

서버엔 요청과 별도로 뒤에서 도는 작업이 있다.
문서를 업로드하면 바로 "접수됐다"고 응답하고, 분석·텍스트 추출·임베딩은 백그라운드에서 처리한다.
사용자를 수십 초씩 기다리게 하지 않으려는 구조다.

여기에 구멍이 있었다.

재시작하면 증발한다

이 백그라운드 작업은 메모리에서만 돈다.
서버가 재시작되면(배포, 메모리 부족으로 강제 종료, 컨테이너 재생성) 그 작업이 통째로 사라진다.

작업 안에 예외 처리를 해 뒀어도 소용없다.
프로세스 자체가 죽으면 예외를 잡을 코드도 같이 죽기 때문이다.

결과가 좋지 않았다.
문서가 "처리 중" 상태로 영원히 멈춘다.
검색도 조회도 안 되는 채로. 실제로 며칠에서 열흘 넘게 고착된 게 여러 건 있었다.

켤 때 되살린다

방향은 분명했다.
상태를 메모리가 아니라 DB에 남기고, 서버가 켜질 때 멈춘 걸 찾아 다시 큐에 넣는다.

"처리 중"으로 남은 문서를 startup 시점에 훑어서 재처리하면 된다.
여기까진 쉽다.

진행 중과 고아를 구분하는 게 핵심

문제는 "처리 중"이 두 종류라는 거였다.

하나는 재시작으로 버려진 고아다. 이건 되살려야 한다.
다른 하나는 방금 정상적으로 시작해서 지금 잘 돌고 있는 작업이다.
이건 건드리면 안 된다. 되살린답시고 다시 큐에 넣으면 같은 작업이 중복 실행된다.

둘을 겉만 봐선 구분할 수 없다. 둘 다 상태가 "처리 중"이다.

그래서 타임스탬프로 갈랐다.
"처리 중"이면서 마지막 갱신이 10분보다 오래된 것만 고아로 보고 복구한다.
방금 시작한 정상 작업은 아직 10분이 안 됐으니 건드리지 않는다.
재시작으로 오래 멈춰 있던 것만 되살아난다.

10분은 정상 처리에 걸리는 최대 시간보다 넉넉히 크게 잡은 값이다.
정상 작업이 그 안에 못 끝날 일은 없고, 재시작된 고아는 그보다 훨씬 오래 멈춰 있으니 안전하게 갈린다.

정리

  • 메모리에서 도는 fire-and-forget 작업은 프로세스가 죽으면 증발한다 — 작업 안 예외 처리로는 못 막는다
  • 상태를 DB에 남기고, 서버가 켜질 때 "처리 중"으로 멈춘 걸 다시 큐에 넣어 복구했다
  • "지금 정상 진행 중"과 "재시작으로 버려진 고아"를 구분하는 게 핵심 — 둘 다 상태는 "처리 중"이다
  • 타임스탬프 가드(마지막 갱신이 10분 초과)로 고아만 골라, 방금 시작한 작업의 중복 실행을 막았다

크래시로 사라지는 작업의 복구는 "무엇을 되살릴지"가 아니라 "무엇을 건드리지 말지"를 정하는 문제였다.

반응형