슬롯 스케줄링의 장점: Ruby 기반 시스템의 부하 분산 전략

Julik Tarkhanov, "On the benefits of slot scheduling"

작성자
EuRuKo
발행일
2025년 01월 13일

핵심 요약

  • 1 Ruby on Rails 기반 핀테크 스타트업 Cheddar는 비효율적인 은행 연동 작업 스케줄링으로 인한 시스템 부하 문제를 겪었습니다.
  • 2 이를 해결하기 위해 시뮬레이션과 Ruby의 Mersenne Twister, GCD 메서드를 활용한 '슬롯 스케줄링' 방식을 도입했습니다.
  • 3 이 새로운 스케줄링 방식은 작업 처리량의 균일화를 달성하여 컴퓨팅 비용을 절감하고 시스템 안정성을 크게 향상시켰습니다.

도입

본 강연은 Ruby 개발 경력 20년 이상의 Ulik이 핀테크 스타트업 Cheddar에서 겪었던 대규모 백그라운드 작업 스케줄링 문제를 다루고, 이를 해결하기 위한 '슬롯 스케줄링' 기법과 그 장점을 소개합니다. 기존의 작업 스케줄링 방식은 일시적인 대량 작업 유입으로 인해 큐 깊이 증가, CPU 부하 상승, 오토스케일링 비용 증가 등 시스템에 불균일한 부하를 초래하는 고질적인 문제를 안고 있었습니다. 특히, 23개 영국 은행과의 연동 작업을 Rails 모놀리스 아키텍처에서 처리하는 Cheddar의 경우, 이러한 부하 불균형은 서비스 안정성과 운영 효율성에 직접적인 영향을 미쳤습니다.

기존의 스케줄링 방식은 주기적으로 업데이트가 필요한 사용자들을 일괄적으로 쿼리하여 대량의 동기화 작업을 큐에 주입하는 형태였습니다. 이는 데이터베이스에 순간적인 부하를 가하고, 오토스케일러가 불필요하게 많은 인스턴스를 생성하게 하여 비용 비효율을 야기했습니다. 이러한 문제를 해결하기 위해 Ulik은 시뮬레이션 기반의 접근 방식을 도입했습니다. 먼저, 실제 작업 소요 시간 분포(APM 데이터를 통한 백분위수)를 반영하여 가짜 작업 지속 시간을 생성하는 시뮬레이터를 구축했습니다. 이 과정에서 컴퓨터 공학 지식이 부족했음에도 불구하고, LLM(ChatGPT)의 도움을 받아 ‘역변환 샘플링(Inverse Transform Sampling)’이라는 통계 기법을 활용하여 실제와 유사한 작업 시간 분포를 모방할 수 있었습니다.

핵심 해결책은 ‘슬롯 스케줄링’입니다. 이는 Ruby의 표준 라이브러리에 포함된 Mersenne Twister라는 예측 가능한 난수 생성기를 활용합니다. 사용자 ID(UUID)를 시드(seed)로 사용하여 각 사용자에게 고유하고 예측 가능한 지연 시간을 할당함으로써, 전체 사용자 기반의 작업을 시간 축에 고르게 분산시킵니다. 또한, 사용자 기반을 여러 개의 ‘슬롯(buckets)’으로 나누어 각 슬롯에 해당하는 사용자들의 작업만 특정 시점에 큐에 주입하는 방식을 도입했습니다. 이 슬롯의 개수는 주기 시간과 바이트의 가능한 값의 개수(256)를 이용하여 Ruby의 gcd (최대 공약수) 메서드로 계산하여 최적화했습니다. 예를 들어, 8시간 주기로 작업을 처리하고 싶다면, gcd를 통해 적절한 슬롯 수를 결정합니다.

작업 실행은 세 단계로 나뉩니다: 전체 사이클을 관리하는 ‘부트스트랩’ 작업, 각 슬롯별 작업을 지연시켜 실행하는 ‘슬롯별’ 작업, 그리고 최종적으로 각 사용자별 동기화 작업을 큐에 넣는 ‘동기화’ 작업입니다. 이 방식은 대량의 작업이 한꺼번에 큐에 유입되는 것을 방지하여 큐 시스템과 데이터베이스의 부하를 크게 줄입니다. 더 나아가, 이 슬롯 스케줄링은 서로 데이터 잠금(lock)이 필요한 ‘결제 승인’과 ‘리포트 생성’과 같은 작업들이 동시에 실행되어 충돌하는 것을 방지하는 데도 활용될 수 있습니다. 즉, 한 작업이 슬롯 0에 할당되면, 다른 충돌 가능성이 있는 작업은 슬롯 4(반대편)에 할당하는 방식으로 동일 계정에 대한 잠금 충돌을 효과적으로 회피합니다. PostgreSQL의 UUID 마지막 바이트를 활용한 사용자 슬롯 할당 기법도 소개되었습니다.

결론

슬롯 스케줄링 도입 결과, Cheddar는 백그라운드 작업 처리량 그래프에서 명확하게 드러나는 극적인 균일화를 달성했습니다. 이는 불필요한 오토스케일링 인스턴스 생성을 줄여 컴퓨팅 비용을 절감하고, 리소스 예측 가능성을 크게 향상시켰습니다. 또한, PG Bouncer와 같은 데이터베이스 연결 관리 문제에서도 자유로워질 수 있었습니다. 비록 '점보 사용자(Jumbo Users)'와 같이 일반적인 사용자보다 훨씬 많은 데이터를 처리하는 예외적인 케이스는 여전히 존재하지만, 이는 별도의 클러스터나 큐를 할당하여 해결할 수 있는 관리 가능한 문제임을 강조했습니다. 결론적으로, Ulik은 '단순한 해결책도 효과적으로 작동할 수 있다'는 점과, 시뮬레이션이 다양한 스케줄링 전략을 평가하는 데 매우 유용하며, 기본적인 통계 지식(Mersenne Twister, GCD 등)이 시스템 최적화에 큰 도움이 된다는 점을 역설하며 강연을 마무리했습니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!