[Django] - Celery

KimJiHong·2023년 12월 19일
1

Django and API

목록 보기
8/9
post-thumbnail

블로그유튜브를 참고하여 개념을 정리한 게시글 입니다.

Celery

Celery는 비동기 분산 작업 Queue 시스템을 구현하기 위한 라이브러리.

프로젝트를 진행하다 보면 처리하는데 오랜 시간이 걸리는 작업이 생겨, 해당 작업이 완료될 때까지 Main thread가 중단되거나 지연되는 일이 발생할 수 있다.

예를 들어 어떤 사용자가 회원가입을 했을 때
Server에서 직접 가입 환영 메일을 보내도록 구현한다면 해당 사용자에게 이메일을 보낼 때 까지 해당 쓰레드는 다른 작업을 처리하지 못하게 된다.

Celery는 이러한 상황을 극복하기 위해 BrokerConsumer(worker)를 통해 비동기적으로 처리하여 사용자에게 가능한 빠르게 응답을 제공한다.
즉, 예시에서 서버가 가입 환영 메일을 보내는 작업을 Broker에게 넘김으로 써 비동기적으로 수행하고 병렬로 연결된 여러 Worker들을 통해 분산 처리를 할 수 있다.

Celery의 구성

Celery는 작업을 처리하기 위해 Producer, Broker, Consumer라는 3가지 핵심 구성 요소를 가지고, 이 3가지 구성 요소는 "메시지" 기반으로 통신을 진행한다.

  • Producer (작업 생성자)
    • Producer는 처리할 작업을 생성하고, 이를 메시지로 Packing하여 Broker로 전송
    • ex) 새로운 사용자에게 이메일 전송 작업 생성
  • Broker (작업 전달 및 작업 임시 대기를 위한 저장소)
    • Broker는 Producer로부터 받은 작업 메시지를 Queue에 저장
    • Queue에 저장된 작업은 등록된 순서대로(FIFO) Worker에게 전달된다.
    • ex) 이메일 전송 작업 임시 대기(바로 앞의 작업이 Worker한테 할당될 때까지)
  • Consumer (작업 수행자)
    • Worker는 Broker로부터 받은 작업 메시지를 가져와 실제 작업을 처리
    • ex) 새로운 사용자에게 이메일 전송!

그럼 사진으로 간단한 흐름을 확인 해보자!

위 사진의 흐름은 아래의 3가지 과정을 거친다.

  1. Producer(사진은 Back-End)에서 Celery 라이브러리를 통해 작업을 생성하고 Messages 형태로 Broker로 전송.

  2. Broker에서는 받은 작업 메시지를 Queue에 적재. (TASK1 - TASK2 순서)

  3. Worker(Celery-Worker)에서 Queue에 적재된 작업 메시지를 받아 처리하고 처리된 작업을 다시 Result Store(DB)에 저장.
    (각각의 Worker는 병렬로 여러 작업을 처리할 수 있다.)

실제로 RabbitMQ를 Broker로 결정했을 때
Broker에서는 ExchangeRoute를 통해 Producer로 부터 받은 작업을 적절한 Queue로 Routing하는 작업을 수행하여 "작업 Message가 최소 한번 이상은 전달"되는 것을 보장한다.

이러한 기법을 ACK 기법이라고 한다.
자세한 설명은 [AMQP] - RabbitMQ ACK, Exchange, Route 게시글에서 확인 가능하다.

Redis vs RabbitMQ (Broker)

장고에서는 Message Broker의 역할을 보통 Redis나 메시지 Queue 기반 시스템인RabbitMQ를 사용하여 구현한다.

  • Redis
    • 장점 : 메모리 기반이라서 매우 빠른 속도를 가진다.
    • 단점 : 큐에 저장된 메시지가 손실될 수 있다.
    • Exchange, Routing 과정 없이 간단한 Broker의 역할.
  • RabbitMQ
    • 장점 : 메시지를 안정적으로 전달할 수 있다. (ACK 기법)
    • 단점 : Redis에 비해 느린 속도를 가진다.
    • Exchange, Routing 과정으로 적어도 한번의 메시지 도착은 보장.

메모리 기반의 데이터 저장소인 Redis는 데이터가 주로 메모리에 상주하기 때문에 읽기/쓰기 연산이 매우 빠르지만, 큐에 저장된 메시지에서 장애 발생시 손상될 수 있다.

그에 반해, RabbitMQACK 기법과 Exchange, Routing을 통해 "At Least Once" 즉, Consumer에게 적어도 한번의 메시지 도착을 보장하기 때문에 메시지 유실의 문제는 거의 없다. 하지만, 안정적인 메시지 전달을 위한 과정으로 인해 Redis에 비해 상대적으로 느린 속도를 가지게 된다.

즉, 안정성이 중요한 작업일 경우에는 RabbitMQ를 Broker로 설정하는 것이 좋고, 상대적으로 덜 중요하고 빠른 속도를 원하는 작업일 경우 Redis를 사용해서 구현하는 것이 좋다.
(속도 vs 안정성)

Ref.

https://saadali18.medium.com/celery-beat-and-redis
https://docs.celeryq.dev/
https://velog.io/@jun17114/message-queue-protocol
https://ordilog.tistory.com/10
https://www.youtube.com/watch?v=hFIkEGtW6vE

profile
대충 할거면 시작도 하지 말자.

0개의 댓글