¿Cómo evitar que tu sitio PHP se «congele» con operaciones largas?
\n\n¿Alguna vez has esperado 30 segundos a que un sitio web envíe un correo de confirmación? ¿O has visto cómo una página se «traba» al generar un informe en PDF? En el mundo de PHP, donde cada solicitud se ejecuta de forma síncrona, estas tareas pueden arruinar la experiencia del usuario. Pero hay una solución probada: colas y tareas en segundo plano. Permiten mover el trabajo «pesado» a un segundo plano, mostrándole al usuario al instante: «¡Su solicitud ha sido recibida!».
\n\nEn este artículo, veremos cómo organizar colas en PHP con herramientas populares: RabbitMQ, Redis y Gearman. Encontrarás ejemplos de código reales, aprenderás a evitar errores comunes y podrás implementar el procesamiento en segundo plano en tu proyecto hoy mismo.
\n\n¿Por qué necesitas colas en PHP?
\n\nTradicionalmente, PHP funciona con el modelo «solicitud-respuesta». Pero cuando llega el momento de operaciones que duran más de 1-2 segundos (enviar correos, procesar imágenes, generar informes, webhooks), el usuario se encuentra con tiempos de espera o simplemente se aburre mirando un spinner. Las colas solucionan este problema de raíz:
\n\n- \n
- Respuesta instantánea — el usuario recibe una respuesta de inmediato, mientras la tarea pesada pasa a segundo plano. \n
- Escalabilidad — puedes ejecutar decenas de workers en paralelo sin modificar el código. \n
- Fiabilidad — si un worker falla, la tarea permanece en la cola y se ejecutará más tarde. \n
- Equilibrio de carga — los picos de carga se suavizan gracias al almacenamiento en búfer. \n
Veamos cómo implementarlo en la práctica usando tres de los enfoques más populares.
\n\n1. Colas con Redis: fácil y rápido
\n\nRedis no es solo una caché. Gracias a sus estructuras de datos (listas, conjuntos) y al mecanismo Pub/Sub, es ideal para colas simples. Si ya tienes Redis en tu servidor, esta es la forma más rápida de implementar tareas en segundo plano sin instalar servicios adicionales.
\n\nEjemplo: cola de envío de correos con Redis
\n\nSupongamos que después del registro de un usuario, necesitas enviar un correo de bienvenida. En lugar de llamar a mail() dentro del controlador, simplemente colocamos la tarea en una cola.
\n\nPaso 1. Agregar una tarea a la cola (productor):
\n\n<?php\n// producer.php\n$redis = new Redis();\n$redis->connect('127.0.0.1', 6379);\n\n$task = json_encode([\n 'type' => 'welcome_email',\n 'user_id' => 42,\n 'email' => 'user@example.com',\n 'created_at' => time()\n]);\n\n// RPUSH agrega un elemento al final de la lista\n$redis->rPush('email_queue', $task);\necho "Tarea agregada a la cola\\n";\n?>\n\nPaso 2. Worker que procesa las tareas (consumidor):
\n\n<?php\n// worker.php\n$redis = new Redis();\n$redis->connect('127.0.0.1', 6379);\n\necho "Worker iniciado, esperando tareas...\\n";\n\nwhile (true) {\n // BLPop bloquea la ejecución hasta que aparezca un elemento\n $taskData = $redis->blPop('email_queue', 5); // timeout de 5 seg\n \n if ($taskData) {\n $task = json_decode($taskData[1], true);\n \n echo "Procesando tarea: {$task['type']} para {$task['email']}\\n";\n \n // Simulación de envío de correo\n sleep(2);\n \n // Aquí iría la lógica real: mail(), SMTP, etc.\n echo "Correo enviado al usuario {$task['user_id']}\\n";\n }\n}\n?>\n\nEjecución:
\nEl worker se ejecuta en segundo plano (con nohup o Supervisor):
php worker.php &\n\nAhora, cuando un usuario se registra, el controlador llama a producer.php y devuelve una respuesta de inmediato, mientras el worker procesa los correos tranquilamente. Redis garantiza que la tarea no se perderá, incluso si el worker falla temporalmente.
2. RabbitMQ: el estándar industrial
\n\nSi tu proyecto está creciendo