Queue یا صف سازوکاری برای جدا کردن تولید کار از زمان پردازش آن است. در یک فروشگاه، درخواست خرید نباید برای تولید PDF فاکتور، ارسال ایمیل و پردازش عکس منتظر بماند. کارها به صف می‌روند و Workerها آن‌ها را دریافت می‌کنند.

صف، بروکر و ورکر چه تفاوتی دارند؟

مفهوممسئولیتنمونه
Queueنگهداری ترتیب یا فهرست کارهاRedis List، Amazon SQS
Message Brokerانتقال و مسیریابی پیامRabbitMQ، ActiveMQ
Workerاجرای کارLaravel Worker، Celery Worker
Event Streamثبت و بازخوانی جریان رخدادKafka، Redis Streams

Job در لاراول

use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
class GenerateInvoice implements ShouldQueue {
    use Queueable;
    public function __construct(public int $orderId) {}
    public function handle(): void {
        // Generate invoice idempotently
    }
}
GenerateInvoice::dispatch($order->id)->onQueue('invoices');

Listener قابل صف در لاراول

use Illuminate\Contracts\Queue\ShouldQueue;
class SendReceipt implements ShouldQueue {
    public function handle(OrderPaid $event): void {
        // Send receipt for this event
    }
}

دستورات رایج Artisan

دستورکاربرد
php artisan queue:workشروع Worker
php artisan queue:work redis --queue=emails --tries=3کار روی صف مشخص با سقف تلاش
php artisan queue:restartدرخواست Restart از Workerهای فعال
php artisan queue:failedدیدن Jobهای ناموفق
php artisan queue:retry allتلاش دوباره همه Jobهای ناموفق
php artisan queue:flushپاک‌سازی فهرست Jobهای ناموفق، با احتیاط
php artisan horizonشروع Horizon روی Redis
php artisan horizon:statusبررسی وضعیت Horizon

Python با Celery

# tasks.py
from celery import Celery
app = Celery('shop', broker='redis://localhost:6379/0')
@app.task
def generate_invoice(order_id: int):
    print('Invoice for', order_id)

generate_invoice.delay(42)
celery -A tasks worker --loglevel=info

Go: الگوی ساده Worker و Channel

jobs := make(chan int, 100)
for i := 0; i < 4; i++ {
    go func() {
        for orderID := range jobs {
            processInvoice(orderID)
        }
    }()
}
jobs <- 42

Channel مثال بالا داخل حافظه یک برنامه است و تضمین ماندگاری ندارد. برای صف پایدار در Go می‌توان از Asynq با Redis، RabbitMQ یا دیگر سرویس‌های سازگار استفاده کرد. در C# نیز BackgroundService و Channel برای پردازش درون‌برنامه‌ای و Hangfire یا MassTransit برای سناریوهای ماندگارتر رایج‌اند.

انتخاب ابزار

ابزاربهتر براینکته
لاراول Horizonمانیتورینگ صف‌های Redis در لاراولفقط اتصال‌های Redis را مدیریت می‌کند
RabbitMQصف با Routing و Ack انعطاف‌پذیرطراحی Exchange و Consumer
Kafkaرخدادهای قابل بازپخش و Stream در مقیاس بالاجایگزین مستقیم همه صف‌های Job نیست
Amazon SQSصف مدیریت‌شده در ابرVisibility Timeout و DLQ
Celeryکارهای پس‌زمینه پایتونWorker و Broker جداگانه
Hangfireکارهای پس‌زمینه .NETStorage مناسب و Dashboard

نکته فنی

پردازش صف را حداقل یک‌بار فرض کنید مگر اینکه تضمین دقیق دیگری دارید. شناسه یکتا، آیدمپوتنسی و مدیریت Retry ضروری‌اند.

اصطلاحات مرتبط: جاب، لسنر، ورکر، صف پیام، مسیج بروکر، ردیس، هورایزن لاراول، صف پیام‌های ناموفق، تحویل حداقل یک‌بار پیام.