0Pricing
PHP Academy · Aula

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 IDE

Produçã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 customerId como 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 — lz4 ou zstd reduz significativamente o custo de rede.
  • acks — all para durabilidade, 1 para 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.ms com um valor generoso para não ser removido do grupo.
  • Defina log_level e 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.size e compression.type; sempre use flush().

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

  1. Por que usar mensageria assíncrona
  2. Trabalhando com RabbitMQ em PHP
  3. Apache Kafka com PHP
  4. Construindo fluxos de trabalho orientados a eventos
← Voltar para PHP Academy