Como evitar que seu site PHP "trave" em operações demoradas?
\n\nVocê já esperou 30 segundos para um site enviar um e-mail de confirmação? Ou viu uma página "congelar" ao gerar um relatório em PDF? No mundo do PHP, onde cada requisição normalmente é executada de forma síncrona, essas tarefas podem destruir a experiência do usuário. Mas existe uma solução comprovada — filas e tarefas em segundo plano. Elas permitem transferir o trabalho "pesado" para os bastidores, mostrando instantaneamente ao usuário: "Sua solicitação foi recebida!".
\n\nNeste artigo, vamos explorar como organizar filas em PHP usando ferramentas populares: RabbitMQ, Redis e Gearman. Você verá exemplos reais de código, aprenderá a evitar erros comuns e poderá implementar o processamento em segundo plano no seu projeto ainda hoje.
\n\nPor que usar filas no PHP?
\n\nTradicionalmente, o PHP opera no modelo "requisição-resposta". Mas quando chega a hora de operações que duram mais de 1-2 segundos (envio de e-mail, processamento de imagens, geração de relatórios, webhooks), o usuário enfrenta timeouts ou simplesmente fica entediado olhando para um spinner. As filas resolvem esse problema de forma radical:
\n\n- \n
- Resposta instantânea — o usuário recebe uma resposta imediata, enquanto a tarefa pesada vai para segundo plano. \n
- Escalabilidade — você pode executar dezenas de workers em paralelo, sem alterar o código. \n
- Confiabilidade — se um worker "cair", a tarefa permanece na fila e será executada depois. \n
- Balanceamento de carga — picos de carga são suavizados através do buffer da fila. \n
Vamos ver como implementar isso na prática, usando três das abordagens mais populares.
\n\n1. Filas com Redis: simples e rápido
\n\nRedis não é apenas um cache. Graças às suas estruturas de dados (listas, conjuntos) e ao mecanismo Pub/Sub, ele é ideal para filas simples. Se você já tem Redis no servidor, esta é a maneira mais rápida de implementar tarefas em segundo plano sem instalar serviços adicionais.
\n\nExemplo: fila de envio de e-mails com Redis
\n\nSuponha que, após o registro de um usuário, seja necessário enviar um e-mail de boas-vindas. Em vez de chamar mail() dentro do controller, simplesmente colocamos a tarefa na fila.
\n\nPasso 1. Adicionar a tarefa à fila (produtor):
\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 adiciona o elemento ao final da lista\n$redis->rPush('email_queue', $task);\necho "Tarefa adicionada à fila\\n";\n?>\n\nPasso 2. Worker que processa as tarefas (consumidor):
\n\n<?php\n// worker.php\n$redis = new Redis();\n$redis->connect('127.0.0.1', 6379);\n\necho "Worker iniciado, aguardando tarefas...\\n";\n\nwhile (true) {\n // BLPop bloqueia a execução até que um elemento apareça\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 "Processando tarefa: {$task['type']} para {$task['email']}\\n";\n \n // Simulação de envio de e-mail\n sleep(2);\n \n // Aqui vai a lógica real: mail(), SMTP, etc.\n echo "E-mail enviado para o usuário {$task['user_id']}\\n";\n }\n}\n?>\n\nExecução:
\nO worker é executado em segundo plano (via nohup ou Supervisor):
php worker.php &\n\nAgora, quando um usuário se registra, o controller chama producer.php e retorna a resposta imediatamente, enquanto o worker processa os e-mails tranquilamente. O Redis garante que a tarefa não será perdida, mesmo que o worker caia temporariamente.
2. RabbitMQ: o padrão da indústria
\n\nSe o seu projeto está crescendo