Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Gửi email, xuất báo cáo, xử lý ảnh... những việc này mà làm ngay trong request thì người dùng phải chờ rất lâu. Hàng đợi (queue) cho phép bạn đẩy việc nặng ra nền và trả lời người dùng ngay lập tức. Laravel hỗ trợ việc này rất gọn gàng.
Thay vì làm việc nặng trong controller, bạn tạo một job mô tả công việc đó và đẩy vào hàng đợi. Một tiến trình riêng gọi là worker sẽ lấy job ra và chạy lần lượt. Request của người dùng kết thúc gần như tức thì.
Laravel hỗ trợ nhiều nơi lưu hàng đợi (driver): database, redis, sqs, beanstalkd. Khi mới học, database là đủ để thử; khi chạy thật, Redis thường là lựa chọn phổ biến nhờ tốc độ.
Tạo job bằng Artisan:
php artisan make:job SendWelcomeEmailRồi viết logic trong phương thức handle:
class SendWelcomeEmail implements ShouldQueue{ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function __construct(public User $user) {} public function handle(): void { Mail::to($this->user->email)->send(new WelcomeMail($this->user)); }}Đẩy job vào hàng đợi ở bất kỳ đâu trong code:
SendWelcomeEmail::dispatch($user);Nhờ trait SerializesModels, Laravel chỉ lưu id của model rồi nạp lại bản mới nhất khi job chạy, nên dữ liệu không bị cũ.
Job chỉ được xử lý khi có worker đang chạy:
php artisan queue:work --tries=3Trên server thật, bạn không thể để lệnh này chạy trong terminal. Hãy dùng Supervisor (hoặc systemd) để giữ worker luôn sống và tự khởi động lại khi chết. Một lưu ý quan trọng: worker là tiến trình chạy lâu, nó nạp code một lần, nên sau mỗi lần deploy bạn cần chạy php artisan queue:restart để worker nhận code mới.
Job có thể thất bại vì mạng chập chờn hay dịch vụ bên ngoài lỗi. Bạn có thể cấu hình ngay trong class:
public int $tries = 3;public array $backoff = [10, 60, 300]; // giây giữa các lần thử lạipublic function failed(Throwable $e): void{ // ghi log hoặc báo cho đội vận hành}Job thử hết số lần vẫn lỗi sẽ được ghi vào bảng failed_jobs. Bạn xem bằng php artisan queue:failed và chạy lại bằng php artisan queue:retry all.
SendReminder::dispatch($user)->delay(now()->addMinutes(10)).onQueue('emails') để tách việc quan trọng khỏi việc ít gấp, rồi chạy worker với --queue=high,default.Bus::chain([...])->dispatch() khi các bước phải chạy theo thứ tự.Nếu dùng Redis, Laravel Horizon cung cấp bảng điều khiển để xem số job đang chờ, thời gian xử lý, job lỗi và tự cân bằng số worker. Đây là công cụ đáng dùng khi hệ thống đã có lượng job đáng kể.
Hãy hình dung người dùng bấm nút xuất báo cáo doanh thu của cả năm. Nếu xử lý đồng bộ, trình duyệt sẽ quay vòng tròn cả phút và có thể bị timeout. Với queue, luồng xử lý trở nên thân thiện hơn rất nhiều:
Cách làm này tách biệt hoàn toàn thời gian xử lý khỏi trải nghiệm người dùng, và nếu job lỗi, bạn có cơ hội thử lại mà không bắt người dùng làm lại từ đầu.
handle.$timeout hợp lý để một job không chiếm worker mãi.afterCommit() để job chỉ được gửi đi sau khi giao dịch hoàn tất.Queue giúp ứng dụng nhanh hơn trong mắt người dùng và chịu tải tốt hơn. Hãy nhớ ba điều: job nhỏ và an toàn khi chạy lại, worker phải được giám sát, và deploy xong phải restart worker. Bắt đầu bằng việc chuyển tác vụ gửi email sang queue là một bước thực hành rất hợp lý.
Nếu muốn luyện tập cùng bài tập thực tế, hãy ghé các khóa học tại codebem.com khi bạn sẵn sàng.
Nguyễn Đình Cường
0 comment