Apache Kafka com PHP
Transmita eventos de alto volume usando Kafka.
Apache Kafka com PHP é uma aula grátis de PHP Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de PHP Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de PHP Academy inclui 4 aulas no total.
Kafka com PHP
Kafka não é uma fila de tarefas — é um registro de confirmações distribuído e somente para acréscimo. Os produtores acrescentam registros aos tópicos; os consumidores leem a partir de seu próprio deslocamento e podem reproduzir o histórico. Isso torna Kafka ideal para fluxos de eventos de alto débito, origem de eventos e alimentação de vários grupos de consumidores independentes a partir de um único fluxo.
No PHP, você se comunica com Kafka por meio de ext-rdkafka, uma vinculação sobre a biblioteca C librdkafka, amplamente testada.
Registro, não fila
A mudança de perspectiva de RabbitMQ para Kafka:
- As mensagens não são excluídas quando consumidas; expiram conforme a política de retenção (por tempo ou tamanho).
- Cada consumidor acompanha seu próprio deslocamento — sua posição no registro.
- Um tópico é dividido em partições; a ordenação é garantida somente dentro de uma partição.
- Vários grupos de consumidores leem the mesmo tópico de forma independente.
Se você precisa reproduzir mensagens, distribuí-las para muitos leitores ou obter um débito enorme, Kafka é adequado. Se precisa de roteamento por mensagem e tempos de expiração, RabbitMQ é adequado.
Instalação do ext-rdkafka
Instale primeiro a biblioteca nativa, depois a extensão PECL e, opcionalmente, um invólucro de nível mais alto.
# Debian/Ubuntu
apt-get install -y librdkafka-dev
pecl install rdkafka
echo "extension=rdkafka.so" >> php.ini
# Optional ergonomic wrapper
composer require longlang/phpkafka # or arnaud-lb/php-rdkafka-stubs for IDEProdução de registros
Crie um RdKafka\Producer, obtenha um identificador de tópico e use produce(). A chave controla em qual partição um registro será colocado — mesma chave, mesma partição, ordem preservada. Sempre use flush() antes de sair ou você perderá os registros armazenados em buffer.
<?php
$conf = new RdKafka\Conf();
$conf->set('bootstrap.servers', 'localhost:9092');
$producer = new RdKafka\Producer($conf);
$topic = $producer->newTopic('orders');
// RD_KAFKA_PARTITION_UA = let the partitioner choose by key
$key = 'order-42';
$topic->produce(RD_KAFKA_PARTITION_UA, 0, json_encode(['id' => 42]), $key);
$producer->poll(0);
$result = $producer->flush(10000); // wait up to 10s
if ($result !== RD_KAFKA_RESP_ERR_NO_ERROR) {
throw new RuntimeException('Failed to flush');
}Particionamento por chave
O particionamento é o centro da escalabilidade e da ordenação do Kafka. O particionador padrão calcula um hash da chave do registro: partition = hash(key) % numPartitions. Escolher uma boa chave é importante:
- Use
customerIdcomo chave → todos os eventos de um cliente permanecem ordenados e em uma única partição. - Chave nula → alternância circular entre as partições (débito máximo, sem ordenação).
Você nunca pode reduzir a quantidade de partições de um tópico, e adicionar partições reorganiza o mapeamento do hash — portanto, dimensione as partições antecipadamente para o paralelismo máximo.
Grupos de consumidores e deslocamentos
Use o KafkaConsumer de alto nível com group.id. Kafka distribui as partições entre os membros do grupo e reequilibra quando membros entram ou saem. Cada membro lê somente as partições atribuídas a ele, proporcionando escalabilidade horizontal gratuitamente.
<?php
$conf = new RdKafka\Conf();
$conf->set('bootstrap.servers', 'localhost:9092');
$conf->set('group.id', 'order-emailers');
$conf->set('auto.offset.reset', 'earliest'); // start of log if no offset
$conf->set('enable.auto.commit', 'false'); // we commit manually
$consumer = new RdKafka\KafkaConsumer($conf);
$consumer->subscribe(['orders']);
while (true) {
$msg = $consumer->consume(5000);
if ($msg->err === RD_KAFKA_RESP_ERR_NO_ERROR) {
handle($msg->payload);
$consumer->commit($msg); // commit offset AFTER work
}
}
function handle(string $p): void {}Quando confirmar
A confirmação do deslocamento define the semântica de entrega:
- Confirme depois do processamento → pelo menos uma vez (uma falha antes da confirmação reproduz o registro).
- Confirme antes do processamento → no máximo uma vez (uma falha o perde).
A confirmação automática (enable.auto.commit=true) confirma em um temporizador, independentemente de o seu trabalho ter terminado — é conveniente, mas pode descartar registros silenciosamente em caso de falha. Desative-a e confirme manualmente quando a correção for importante.
Tratamento de erros de consumo
Nem todo retorno de consume() é uma mensagem. Você deve ramificar com base no código de erro — __PARTITION_EOF e __TIMED_OUT são sinais normais de controle, não falhas.
<?php
$msg = $consumer->consume(2000);
switch ($msg->err) {
case RD_KAFKA_RESP_ERR_NO_ERROR:
echo "Got: {$msg->payload} @ offset {$msg->offset}\n";
break;
case RD_KAFKA_RESP_ERR__PARTITION_EOF:
echo "Reached end of partition\n"; // caught up, keep polling
break;
case RD_KAFKA_RESP_ERR__TIMED_OUT:
echo "No message this poll\n";
break;
default:
throw new \Exception($msg->errstr(), $msg->err);
}Ajuste do débito
O débito do Kafka vem do processamento em lotes. Principais configurações do produtor:
linger.ms— aguarda brevemente para agrupar mais registros por solicitação (por exemplo, 5–20 ms).batch.size/queue.buffering.max.messages— buffers maiores, menos viagens de ida e volta.compression.type—lz4ouzstdreduz significativamente o custo de rede.acks—allpara durabilidade,1para menor latência.
<?php
$conf = new RdKafka\Conf();
$conf->set('bootstrap.servers', 'localhost:9092');
$conf->set('compression.type', 'lz4');
$conf->set('linger.ms', '10');
$conf->set('batch.size', '65536');
$conf->set('acks', 'all');
$producer = new RdKafka\Producer($conf);Funções de retorno de relatório de entrega
Como produce() é assíncrono, uma falha no envio não gerará uma exceção imediatamente. Registre uma função de retorno de relatório de entrega na configuração do produtor para descobrir o destino de cada registro — essa é the única forma confiável de detectar falhas silenciosas do produtor em PHP.
<?php
$conf = new RdKafka\Conf();
$conf->set('bootstrap.servers', 'localhost:9092');
$conf->setDrMsgCb(function ($producer, $msg) {
if ($msg->err) {
fwrite(STDERR, 'Delivery FAILED: ' . rd_kafka_err2str($msg->err) . "\n");
} else {
echo "Delivered to partition {$msg->partition} @ offset {$msg->offset}\n";
}
});
$producer = new RdKafka\Producer($conf);
// poll() services the callback queue; call it after producing
$producer->poll(0);Armadilhas específicas do PHP
Kafka pressupõe clientes de longa duração; o ciclo de requisição do PHP dificulta isso:
- Os produtores armazenam dados em buffer de forma assíncrona — sempre use
flush()antes que o script termine ou os registros serão perdidos. - Execute os consumidores como processos CLI persistentes sob um supervisor, nunca dentro de uma requisição web.
- Os reequilíbrios pausam o consumo; mantenha curto o trabalho por mensagem ou use
max.poll.interval.mscom um valor generoso para não ser removido do grupo. - Defina
log_levele registre a função de retorno de relatório de entrega do produtor para detectar falhas silenciosas.
Verificação rápida
Garantias de ordenação no Kafka.
Recapitulação
Kafka à maneira do PHP:
- Kafka é um registro reproduzível, não uma fila; os consumidores acompanham os deslocamentos.
- O particionamento por chave oferece ordenação e escalabilidade por chave.
- Os grupos de consumidores dividem as partições e se reequilibram automaticamente.
- Confirme os deslocamentos depois do trabalho para obter pelo menos uma entrega; desative a confirmação automática para ter controle.
- Ajuste
linger.ms,batch.sizeecompression.type; sempre useflush().
Próximo: integrar esses componentes básicos a fluxos de trabalho orientados a eventos confiáveis.
Perguntas Frequentes
A aula “Apache Kafka com PHP” é grátis?
Sim — o texto completo de “Apache Kafka com PHP” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de PHP Academy, atualize para CoddyKit PRO. O curso de PHP Academy inclui 4 aulas no total.
O que vou aprender em “Apache Kafka com PHP”?
Transmita eventos de alto volume usando Kafka. Você pratica PHP Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar PHP Academy?
Nenhuma experiência prévia é necessária. PHP Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Apache Kafka com PHP”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de PHP Academy?
Sim. Cada aula de PHP Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que usar mensageria assíncrona
- Trabalhando com RabbitMQ em PHP
- Apache Kafka com PHP
- Construindo fluxos de trabalho orientados a eventos