Celery: xử lý tác vụ nền và hàng đợi công việc

Người dùng bấm “Đăng ký” và phải chờ 8 giây vì hệ thống đang gửi email. Giải pháp: trả lời ngay, còn việc gửi email đẩy sang hàng đợi cho worker xử lý. Đó chính là Celery.

Cài đặt

pip install "celery[redis]"
# Cần một message broker, thường là Redis
docker run -d -p 6379:6379 redis

Định nghĩa tác vụ

# tasks.py
from celery import Celery

app = Celery("ung_dung", broker="redis://localhost:6379/0",
             backend="redis://localhost:6379/1")

@app.task
def gui_email(dia_chi, tieu_de):
    # ... gửi email thật ở đây
    return f"Đã gửi tới {dia_chi}"

@app.task
def tao_bao_cao(thang):
    # công việc nặng, chạy vài phút
    return f"Báo cáo tháng {thang}"

Chạy worker

celery -A tasks worker --loglevel=info --concurrency=4

Gọi tác vụ từ ứng dụng

from tasks import gui_email

# Không chờ kết quả — trả về ngay lập tức
gui_email.delay("[email protected]", "Chào mừng")

# Cần theo dõi kết quả
ket_qua = gui_email.delay("[email protected]", "Hóa đơn")
print(ket_qua.id)
print(ket_qua.ready())            # xong chưa?
print(ket_qua.get(timeout=30))    # chờ và lấy kết quả

Tự thử lại khi lỗi

@app.task(bind=True, max_retries=3, default_retry_delay=60)
def goi_api(self, url):
    try:
        return requests.get(url, timeout=10).json()
    except requests.RequestException as e:
        raise self.retry(exc=e)   # thử lại sau 60 giây

Lên lịch định kỳ với Celery Beat

from celery.schedules import crontab

app.conf.beat_schedule = {
    "bao-cao-hang-ngay": {
        "task": "tasks.tao_bao_cao",
        "schedule": crontab(hour=7, minute=0),
        "args": ("09",),
    },
}
celery -A tasks beat --loglevel=info

Ba nguyên tắc thực chiến

  1. Chỉ truyền dữ liệu nhỏ. Gửi ID bản ghi, không gửi cả đối tượng — tham số phải chuyển được sang JSON.
  2. Viết tác vụ idempotent. Chạy hai lần vẫn cho kết quả đúng, vì worker có thể xử lý lại sau sự cố.
  3. Đặt thời gian giới hạn. @app.task(time_limit=300) để một tác vụ treo không chiếm worker mãi mãi.

Nếu nhu cầu của bạn chỉ là vài tác vụ nền đơn giản, arq hay RQ nhẹ hơn nhiều. Celery đáng dùng khi bạn cần lịch chạy, thử lại, định tuyến hàng đợi và giám sát ở quy mô thật.

Lên đầu trang