0Pricing
PHP Academy · 강의

PHP용 Apache Kafka

Kafka를 사용해 높은 처리량의 이벤트를 스트리밍합니다.

PHP용 Apache Kafka은(는) CoddyKit의 무료 PHP Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 PHP Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

PHP로 카프카 사용

카프카는 작업 큐가 아니라 분산 추가 전용 커밋 로그입니다. 생산자는 토픽에 레코드를 추가하고, 소비자는 자신의 오프셋에서 읽으며 기록을 다시 재생할 수 있습니다. 따라서 카프카는 높은 처리량의 이벤트 스트림, 이벤트 소싱, 하나의 스트림을 여러 독립 소비자 그룹에 공급하는 데 적합합니다.

PHP에서는 검증된 C 라이브러리 librdkafka를 기반으로 하는 바인딩인 ext-rdkafka를 통해 카프카와 통신합니다.

큐가 아닌 로그

RabbitMQ에서 카프카로 전환할 때는 다음과 같이 관점을 바꿔야 합니다.

  • 메시지는 소비될 때 삭제되지 않고 시간이나 크기에 따른 보존 정책에 따라 만료됩니다.
  • 각 소비자는 자신의 오프셋, 즉 로그에서의 위치를 추적합니다.
  • 토픽은 파티션으로 나뉘며, 순서는 파티션 내부에서만 보장됩니다.
  • 여러 소비자 그룹이 같은 토픽을 서로 독립적으로 읽습니다.

재생, 여러 독자에 대한 다중 분배 또는 막대한 처리량이 필요하다면 카프카가 적합합니다. 메시지별 라우팅과 만료 시간이 필요하다면 RabbitMQ가 적합합니다.

ext-rdkafka 설치

먼저 네이티브 라이브러리를 설치하고, 그다음 PECL 확장을 설치한 후, 필요하다면 더 높은 수준의 래퍼를 설치합니다.

# 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

레코드 생성

RdKafka\Producer를 생성하고 토픽 핸들을 가져온 다음 produce()를 호출합니다. 키는 레코드가 들어갈 파티션을 결정하므로 같은 키는 같은 파티션에 들어가고 순서가 유지됩니다. 종료하기 전에 항상 flush()를 호출하십시오. 그렇지 않으면 버퍼에 남은 레코드를 잃게 됩니다.

<?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');
}

키에 따른 파티션 분할

파티션 분할은 카프카의 확장성과 순서를 결정하는 핵심입니다. 기본 파티셔너는 레코드 키를 해시합니다. partition = hash(key) % numPartitions와 같습니다. 좋은 키를 선택하는 것이 중요합니다.

  • customerId를 키로 사용하면 고객 한 명의 모든 이벤트가 한 파티션에 순서대로 유지됩니다.
  • 널 키를 사용하면 파티션 전체에 순환 분배됩니다. 처리량은 최대가 되지만 순서는 보장되지 않습니다.

토픽의 파티션 수는 줄일 수 없으며, 파티션을 추가하면 해시 매핑이 재배치됩니다. 따라서 최대 병렬 처리량에 맞게 파티션 수를 미리 정하십시오.

소비자 그룹 및 오프셋

KafkaConsumer와 group.id를 사용하는 고수준 소비자를 사용합니다. 카프카는 그룹 구성원 전체에 파티션을 할당하고, 구성원이 참여하거나 나가면 재분배합니다. 각 구성원은 할당된 파티션만 읽으므로 별도 작업 없이 수평 확장을 할 수 있습니다.

<?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 {}

커밋 시점

오프셋 커밋은 메시지 전달 방식을 결정합니다.

  • 처리 후 커밋하면 최소 한 번 전달됩니다. 커밋 전에 충돌이 발생하면 레코드가 다시 재생됩니다.
  • 처리 전에 커밋하면 최대 한 번 전달됩니다. 충돌이 발생하면 레코드를 잃습니다.

자동 커밋(enable.auto.commit=true)은 작업 완료 여부와 관계없이 타이머에 따라 커밋합니다. 편리하지만 충돌이 발생하면 레코드가 조용히 삭제될 수 있습니다. 정확성이 중요하다면 자동 커밋을 끄고 직접 커밋하십시오.

소비 오류 처리

consume()의 모든 반환값이 메시지는 아닙니다. 오류 코드에 따라 분기해야 합니다. __PARTITION_EOF와 __TIMED_OUT은 실패가 아니라 정상적인 제어 신호입니다.

<?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);
}

처리량 조정

카프카의 처리량은 일괄 처리에서 나옵니다. 주요 생산자 설정은 다음과 같습니다.

  • linger.ms — 요청당 더 많은 레코드를 묶을 수 있도록 잠시 기다립니다(예: 5–20ms).
  • batch.size / queue.buffering.max.messages — 버퍼가 커지므로 왕복 횟수가 줄어듭니다.
  • compression.type — lz4 또는 zstd를 사용하면 네트워크 비용을 크게 줄일 수 있습니다.
  • acks — 내구성을 위해 all을 사용하고, 지연 시간을 줄이려면 1을 사용합니다.
<?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);

전달 보고 콜백

produce()는 비동기 방식이므로 전송 실패가 즉시 예외를 발생시키지 않습니다. 생산자 설정에 전달 보고 콜백을 등록하여 각 레코드의 결과를 확인하십시오. 이는 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);

PHP 특유의 주의점

카프카는 오래 유지되는 클라이언트를 전제로 하지만 PHP의 요청 수명 주기는 이에 맞지 않습니다.

  • 생산자는 비동기 방식으로 버퍼링하므로, 스크립트가 끝나기 전에 항상 flush()를 호출하십시오. 그렇지 않으면 레코드를 잃습니다.
  • 소비자는 웹 요청 안에서 실행하지 말고, 감독자 아래의 지속적인 CLI 작업자로 실행하십시오.
  • 재분배가 발생하면 소비가 일시 중지됩니다. 메시지별 작업을 짧게 유지하거나 max.poll.interval.ms를 충분히 크게 설정하여 그룹에서 제외되지 않도록 하십시오.
  • log_level을 설정하고 생산자의 전달 보고 콜백을 등록하여 조용한 실패를 감지하십시오.

빠른 확인

카프카에서 순서가 보장되는 범위.

복습

PHP 방식으로 카프카를 사용하면 다음과 같습니다.

  • 카프카는 큐가 아니라 재생 가능한 로그이며, 소비자는 오프셋을 추적합니다.
  • 키에 따른 파티션 분할로 키별 순서와 확장성을 확보합니다.
  • 소비자 그룹은 파티션을 나누어 처리하고 자동으로 재분배합니다.
  • 최소 한 번 전달을 위해 작업 후에 오프셋을 커밋하고, 제어가 필요하면 자동 커밋을 끕니다.
  • linger.ms, batch.size, compression.type을 조정하고 항상 flush()를 호출합니다.

다음은 이러한 기본 요소를 신뢰할 수 있는 이벤트 기반 작업 흐름으로 연결하는 방법입니다.

자주 묻는 질문

“PHP용 Apache Kafka” 강의는 무료인가요?

네 — “PHP용 Apache Kafka” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 PHP Academy 강의 전체를 잠금 해제할 수 있습니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“PHP용 Apache Kafka”에서 뭘 배우나요?

Kafka를 사용해 높은 처리량의 이벤트를 스트리밍합니다. 브라우저에서 직접 실행하는 실습 코드로 PHP Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

PHP Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 PHP Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“PHP용 Apache Kafka” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 PHP Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 PHP Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 비동기 메시징이 필요한 이유
  2. PHP에서 RabbitMQ 다루기
  3. PHP용 Apache Kafka
  4. 이벤트 기반 워크플로 구축
← PHP Academy(으)로 돌아가기