배치 처리 모범 사례
GitLab에서 사용하는 배치 처리 전략(루프 기반, 단일 칼럼, 키셋, 오프셋, 그룹 계층 등)의 장단점과 올바른 사용 방법을 설명합니다.
이 문서는 GitLab에서 사용하는 배치 처리 전략에 대한 개요를 제공합니다. 엔지니어가 자신의 사용 사례에 맞는 최적의 접근 방식을 선택할 수 있도록 각 전략의 장단점을 정리하였습니다. 배치 처리가 필요한 이유 # 대량의 레코드를 다룰 때, 하나의 데이터베이스 쿼리로 레코드를 읽거나 업데이트하거나 삭제하는 것은 어려울 수 있습니다. 이러한 작업은 쉽게 타임아웃될 수 있습니다. 이 문제를 피하기 위해 레코드를 배치 단위로 처리해야 합니다. 배치 처리는 주로 백그라운드 job에서 이루어지며, 웹 요청에 비해 런타임 제약이 더 완화되어 있습니다. 배치 처리는 백그라운드 job에서만 사용하고 웹 요청에서는 사용하지 말 것 # 드문 경우(오래된 기능)에는 웹 요청에서도 배치 처리가 이루어집니다. 그러나 새로운 기능에서는 짧은 웹 요청 타임아웃(기본값 60초) 때문에 권장하지 않습니다. 지침으로서, 대량의 레코드를 처리해야 하는 기능을 구현할 때는 백그라운드 job(Sidekiq 워커)을 첫 번째 옵션으로 고려해야 합니다. 성능 고려사항 # 배치 처리 성능은 페이지네이션 성능과 밀접하게 관련되어 있으며, 기반 라이브러리와 데이터베이스 쿼리가 본질적으로 동일합니다. 배치 처리를 구현할 때는 페이지네이션 성능 가이드라인 과 배치 처리 유틸리티 관련 문서를 숙지하는 것이 중요합니다. 백그라운드 job에서의 배치 처리 # 백그라운드 job에서 배치 처리를 구현할 때 고려해야 할 두 가지 주요 측면이 있습니다: 총 런타임과 데이터 수정 볼륨입니다. 백그라운드 job은 오랫동안 실행되어서는 안 됩니다. Sidekiq 프로세스는 충돌하거나 강제로 중지될 수 있습니다(예: 재시작 또는 배포 시). 또한 오류 예산 규칙에 따라, 런타임이 5분을 초과하면 해당 기능이 등록된 그룹에 오류 예산 위반이 추가됩니다. 백그라운드 job에서 배치 처리를 구현할 때는 멱등성 job 관련 가이드라인을 숙지해야 합니다. 대량의 레코드를 업데이트하거나 삭제하면 데이터베이스 복제 지연이 증가하고 주 데이터베이스에 추가적인 부하가 가해질 수 있습니다. 백그라운드 job 내에서 처리(또는 배치 처리)하는 레코드의 총 수를 제한하는 것이 바람직합니다. 위에서 언급한 잠재적 문제를 해결하기 위해 다음과 같은 조치를 고려해야 합니다: job의 총 런타임을 제한합니다. 레코드 수정 횟수를 제한합니다. 배치 사이의 휴식 시간을 둡니다. (몇 밀리초) 제한을 적용할 때 중요한 점은, 장시간 실행되는 백그라운드 job은 제한에 도달한 후 배치 처리가 중단된 위치에서 작업을 계속하기 위해 새로운 job이 예약되는 "나중에 계속하기(continue later)" 메커니즘을 구현해야 한다는 것입니다. 이는 job이 너무 길어서 5분 런타임에 맞지 않을 가능성이 높을 때 중요합니다. Gitlab::Metrics::RuntimeLimiter 클래스를 사용한 런타임 제한 구현 예시: def perform(project_id) runtime_limiter = Gitlab::Metrics::RuntimeLimi