파이썬 예약 작업 중복 실행은 먼저 max_instances를 바꾸기보다 실행 로그와 스케줄러 프로세스 수를 분리해 확인해야 합니다. 두 기록의 scheduled run time이 다르면 누락 실행 재처리일 수 있고, 같은 시각에 두 프로세스가 실행했다면 스케줄러 자체가 중복 기동된 상황일 수 있습니다. 이 구분이 끝나야 max_instances, coalesce, misfire_grace_time 중 무엇을 조정할지 결정할 수 있습니다.
먼저 로그에서 확인할 세 가지
작업 시작 로그에 작업 ID, scheduled run time, 실제 시작 시각, 프로세스 식별 정보를 함께 남겨 보십시오. 운영 관점에서 먼저 보는 부분은 “같은 예약 시각을 두 프로세스가 처리했는가”입니다.
- 같은 scheduled run time이 거의 동시에 두 번 기록되면 프로세스나 스케줄 등록이 중복되었는지 확인합니다.
- 서로 다른 scheduled run time이 짧은 간격으로 처리되면 재시작·지연 뒤 누락 실행이 이어진 것인지 살핍니다.
- 시작 로그는 한 번인데 외부 결과만 두 개라면 작업 내부의 재시도나 결과 저장 로직도 분리해서 봅니다.
이 로그만으로 원인을 단정할 수는 없습니다. 다만 설정을 무작정 바꾸기 전에 어느 계층에서 두 번째 실행이 생겼는지 좁히는 기준이 됩니다.
APScheduler 설정 세 가지를 구분하기
APScheduler 3.x 공식 문서에서 각각의 역할은 다릅니다.
max_instances는 같은 작업이 동시에 실행될 수 있는 수를 제한합니다. 작업이 아직 끝나지 않았는데 다음 실행 시점이 오면, 동시 실행을 허용할지 제한할 때 보는 값입니다.
coalesce는 여러 번 처리할 기회가 쌓였을 때 실행을 하나로 합칠지 결정합니다. 따라서 이미 실행 중인 작업을 잠그는 설정이 아니라, 누적된 실행 시점을 어떻게 처리할지에 관한 정책입니다.
misfire_grace_time은 예정 시각을 놓친 실행을 얼마나 늦게라도 허용할지 판단하는 기준입니다. 재시작이나 지연 뒤 실행이 이어졌다면 이 설정과 누락된 실행 시각을 함께 확인해야 합니다.
자세한 동작은 APScheduler 3.x User guide에서 확인할 수 있습니다. 최신 APScheduler 문서는 4.x 계열 용어를 사용하므로, 3.x 설정을 보고 있다면 실제 설치 버전과 문서 버전을 먼저 맞추십시오.
프로세스가 두 개 떠 있는지 확인하기
작업 등록 코드가 정상이어도 애플리케이션이 두 번 시작되면 각 프로세스가 같은 예약 작업을 등록할 수 있습니다. 특히 여러 프로세스가 하나의 영속 job store를 공유하는 구조라면 APScheduler 3.x에서 프로세스 간 조정이 보장되지 않는다고 공식 FAQ가 설명합니다. APScheduler FAQ를 기준으로 배포 구조를 확인하십시오.
저라면 다음 순서로 확인합니다.
- 프로세스 시작 로그에서 스케줄러 인스턴스 수와 프로세스 ID를 확인합니다.
- 각 인스턴스가 같은 job ID를 등록했는지 확인합니다.
- 웹 워커마다 스케줄러를 시작하는 구조라면 스케줄러를 전용 프로세스로 분리할지 검토합니다.
- 배포 재시작 시 이전 프로세스가 완전히 종료되기 전에 새 프로세스가 시작되는지도 봅니다.
여러 스케줄러를 함께 운영해야 한다면 버전에 맞는 조정 방식이 필요합니다. 최신 문서의 다중 스케줄러 기능을 3.x 설정에 그대로 적용해서는 안 됩니다.
설정을 바꿔도 필요한 작업 설계
중복 실행을 줄이는 것과 작업 결과가 중복되지 않는 것은 별개의 문제입니다. 외부 API 호출, 파일 생성, 주문·알림 기록처럼 재실행될 수 있는 작업은 실행 ID나 업무 키를 기준으로 이미 처리한 결과인지 확인하는 방식이 필요합니다.
다만 이 글의 자료만으로 특정 저장소나 분산락 구현이 항상 중복을 제거한다고 말할 수는 없습니다. 작업이 재실행되어도 안전한지, 실패 뒤 어느 단계부터 다시 처리할지, 결과 기록을 먼저 남길지 등을 업무 단위로 정해야 합니다.
점검 순서 요약
먼저 같은 scheduled run time의 중복인지, 서로 다른 누락 실행의 연속인지 구분하십시오. 그다음 스케줄러 프로세스 수와 job 등록 수를 확인하고, 마지막으로 작업 지속시간에 맞춰 max_instances, 누적 실행 정책에 맞춰 coalesce, 지연 허용 범위에 맞춰 misfire_grace_time을 검토하면 됩니다.
이 순서로도 원인이 분명하지 않다면 다음 질문으로 범위를 좁힐 수 있습니다. 실행 ID와 scheduled run time을 어떻게 로그에 남길지, cron·APScheduler·systemd 중 어느 계층에서 중복이 생겼는지, 실패 후 재실행해도 결과가 중복되지 않게 작업을 어떻게 설계할지입니다.