Apache Kafkaは、発生したイベントを追記型のログとして保存し、複数のシステムが同じデータをそれぞれのペースで読み取れるようにする分散ストリーミング基盤です。2025年3月18日に公開された4.0でZooKeeperへの依存が完全に断たれ、構成はKRaftモードだけになりました。この記事では、Kafkaの構造と用語、最新の安定版4.3.1を手元で動かす手順、そしてKafkaを選ぶべき場面と選ぶべきでない場面を、設定値と公式の記述に紐づけて整理します。
まとめ
- Kafkaはメッセージキューではなく追記型の分散ログ。読み取ってもデータは消えず、保持期間(既定168時間)まで何度でも読み直せる
- スループットと順序保証を決めるのはパーティション。順序が守られるのはパーティション内だけで、キーの設計がそのまま並列度の設計になる
- 4.0(2025年3月18日)でZooKeeperが削除され、4.3もKRaftモードのみ。ZooKeeper構成のクラスタは先にKRaftへ移行しないと4.xへ上げられない(3.3.xより古いKRaftクラスタは3.9.x経由が推奨)
- 4.0でBroker・Connect・ToolsのJava要件が17以上に上がった。クライアント側はBroker 2.1以上が前提
- 単発ジョブのキューや優先度付き配信が欲しいだけなら、Kafkaは運用コストに見合わない
以下、構造の理解から4系の変更点、最小構成での起動手順までを順に見ていきます。
Apache Kafkaの正体:イベントを追記するだけの分散ログ
Kafkaは2011年にLinkedInからオープンソース化され、現在はApache Software Foundationが管理しています。中心にあるのは「トピック」という名前の付いたログで、送信されたイベントは末尾に追記されるだけです。書き込み側はログの末尾に足し、読み取り側は自分が読んだ位置を覚えながら先頭から順に読む。この単純さが、毎秒数十万件規模の書き込みを1つのクラスタで受けられる根拠になっています。
公式ドキュメントがGCチューニングの例として挙げているLinkedInの最繁忙クラスタは、60ブローカーで50,000パーティション(レプリケーション係数2)を抱え、毎秒80万メッセージ・受信300MB/秒・送信1GB/秒超を処理しているとされています。同クラスタの90パーセンタイルのGC停止時間は約21ミリ秒です。
「読んでも消えない」ログ構造とメッセージキューとの差
RabbitMQやAmazon SQSのような従来のメッセージキューは、コンシューマが受け取って確認応答を返した時点でメッセージを削除します。Kafkaは削除しません。ブローカー設定log.retention.hoursの既定値は168、つまり7日間はディスクに残り続けます。
この差は運用の選択肢を変えます。バグを含んだ集計処理をデプロイしてしまっても、オフセットを巻き戻せば同じイベント列を最初から処理し直せます。分析基盤と通知処理と監査ログの3系統が、互いに干渉せず同じトピックを読めます。設計思想レベルでの比較はRabbitMQとKafkaの違いで整理しています。
Producer・Broker・Consumerの3役とトピックの位置づけ
Producerはイベントを書き込むクライアント、Consumerは読み取るクライアント、Brokerはトピックのログを保持して両者に応答するサーバープロセスです。KRaftモードではこれに加えて、クラスタのメタデータ(どのトピックがどのブローカーにあるか、誰がリーダーか)をRaftプロトコルで合意するcontrollerロールが存在します。1台のプロセスにbrokerとcontrollerの両方の役割を持たせることもでき、開発環境の1ノード構成はこの形になります。
パーティションとオフセット:並列度と順序保証を決める設計軸
Kafkaを触り始めた段階でつまずきやすいのがここです。トピックは論理的な単位にすぎず、実体は複数のパーティションに分割されています。この分割の仕方が、スループットの上限と順序保証の範囲を同時に決めます。
パーティション数が決める並列度の上限
1つのパーティションは、同じConsumer Group内では常に1つのコンシューマだけが読みます。したがってパーティション数が、そのグループで並列に走らせられるコンシューマの上限です。パーティションを3つ持つトピックに4つ目のコンシューマを足しても、4つ目は何も割り当てられず待機するだけになります。現在の分割数は--describeで確認できます(トピックの作成手順は後述します)。
$ bin/kafka-topics.sh --describe --topic quickstart-events --bootstrap-server localhost:9092
Topic: quickstart-events TopicId: NPmZHyhbR9y00wMglMH2sg PartitionCount: 1 ReplicationFactor: 1 Configs:
Topic: quickstart-events Partition: 0 Leader: 0 Replicas: 0 Isr: 0
ブローカー設定num.partitionsの既定値は1です。自動作成されたトピックをそのまま使うと、並列度1のまま本番に入ってしまいます。順序が保証されるのもパーティション内だけなので、「同じ注文IDのイベントは必ず順番に処理したい」なら注文IDをメッセージキーにして同じパーティションへ寄せる、という設計が必要です。
オフセットとConsumer Groupによる読み取り位置の管理
オフセットはパーティション内での通し番号です。Kafkaはコンシューマごとの配信状態を持たず、「このグループはこのパーティションのどこまで読んだか」というオフセットだけを内部トピックに記録します。書き込み済みの末尾オフセットとコミット済みオフセットの差がコンシューマラグで、遅延を検知する第一の指標になります。
$ bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group my-group
ラグの継続的な監視方法や、ISR・ディスクと合わせてどの指標を選ぶかはKafka監視の指標選定とJMX取得経路で扱っています。
レプリカ・ISR・acksの組み合わせで決まる耐久性
各パーティションはレプリケーション係数の数だけ複製され、リーダーに追いついている複製の集合をISR(In-Sync Replicas)と呼びます。どこまで書き込めば「成功」とみなすかを決めるのがProducer側のacksで、既定値はallです。あわせてenable.idempotenceも既定でtrueになっているため、初期状態のProducerは再送による重複を作らない設定で動きます。
注意が要るのはブローカー側のdefault.replication.factorで、こちらの既定値は1です。複製が1本しかないトピックではacks=allを指定しても守られるのは1台分で、そのブローカーのディスクが飛べばデータは戻りません。本番では作成時にレプリケーション係数とmin.insync.replicasを明示してください。Producer・Consumer側の設定の詳細はKafka Java APIのacks・べき等性とコミット方式にまとめています。
Kafka 4系の構成変更:ZooKeeper廃止とKRaftへの一本化
Kafkaを解説した日本語記事の多くは3.x時代に書かれており、「まずZooKeeperを起動し、次にBrokerを起動する」という手順が前提になっています。この手順は4系では実行できません。ZooKeeperは削除されたからです。
| バージョン | 公開日 | この版で変わったこと |
|---|---|---|
| 4.0.0 | 2025年3月18日 | ZooKeeper削除・KRaft既定化/KIP-848 GA |
| 4.1.0 | 2025年9月2日 | Queues preview・Streams新プロトコルearly access |
| 4.2.0 | 2026年2月17日 | Share Group本番利用可・Java 25対応 |
| 4.3.0 | 2026年5月22日 | 25 KIP・ログdirのcordon |
| 4.3.1 | 2026年6月25日 | 最新安定版(バグ修正) |
4.2.1・4.1.2も並行してサポート対象です。以下、実装判断に影響する4点を個別に見ます。
4.0(2025年3月18日)でのZooKeeper完全削除
4.0はZooKeeperを一切使わずに動く最初のメジャーリリースです。メタデータはKafka自身がRaftプロトコルで管理し、別プロセス群を並べて監視する必要がなくなりました。KRaftモードで本番利用可能と判断されたのは3.3.xからで、4.3の公式アップグレード手順も「ソフトウェアとメタデータのバージョンが最低3.3.x」を要求しています。
移行を先送りしてきた現場にとって重要なのは順序です。ZooKeeper構成のクラスタは、4.xへ直接上げられません。いったんKRaftモードへ移行してから4.xへ進む必要があり、3.3.xより古いKRaftクラスタも3.9.xを経由することが推奨されています。移行手順の具体はKafka KRaftの構成とZooKeeperからの移行手順で解説しています。
KIP-848による「stop-the-world」リバランスの解消
従来のConsumer Groupは、既定の割り当て方式ではメンバーが1つ増減するたびにグループ全体が処理を止めて割り当てをやり直していました。コンシューマ数が数百に達する構成では、この停止時間が無視できない障害要因になります。4.0で一般提供となったKIP-848の新プロトコルは、この全停止を伴わない割り当てに置き換えました。
サーバー側は既定で有効ですが、クライアントは自動では切り替わりません。コンシューマ側でgroup.protocol=consumerを指定してオプトインする必要があります。4.0へ上げただけで効果が出ていると思い込まないでください。
KIP-932は、1つのトピックを複数のコンシューマで分担して消費する「協調消費」をKafkaに持ち込む提案です。従来のConsumer Groupがパーティション単位でしか分担できなかったのに対し、Share Groupはレコード単位で分担できます。パーティション数を超える台数でスケールしたいキュー的な用途がこれで扱えます。
公開の段階は3回に分かれました。4.0でearly access、4.1でpreview、そして4.2で本番利用可能になっています。処理時間が延びたときに確認応答期限を延長するRENEWや、ラグメトリクスが揃ったのは4.2です。4.0や4.1のドキュメントを読んで「まだ使えない」と判断した記憶があるなら、4.2以降で見直す価値があります。
Java要件の引き上げとクライアント側の下限
4.0でJavaの必要バージョンが上がりました。Broker・Connect・ToolsはJava 17以上、ClientsとKafka StreamsはJava 11以上です(KIP-750およびKIP-1013)。4.3のドキュメントでは、Java 17・21・25が完全にサポートされ、Java 11はclientsやstreamsなど一部モジュールに限ってサポートされる、と記載されています。
バージョンの下限は双方向にかかります。KIP-896により、Javaクライアント(ConnectとStreamsを含む)を4.0へ上げる前に接続先のBrokerが2.1以上である必要があり、逆にBrokerを4.0へ上げる前にJavaクライアントが2.1以上である必要もあります。片側だけを先に上げると接続できなくなるため、両方向の下限を確認してから作業してください。
Kafka 4.3.1を最小構成で動かす手順
手を動かすのが最短です。ZooKeeperの起動が不要になった分、4系の起動手順は3系より短くなりました。以下は公式クイックスタートの4.3.1向け手順です。
ダウンロード版:クラスタIDの生成からBroker起動まで
Java 17以上が入った環境で、配布物を展開してクラスタIDを発行し、ログディレクトリをフォーマットしてから起動します。--standaloneはcontrollerとbrokerを1プロセスに同居させる単一ノード用の指定です。
$ tar -xzf kafka_2.13-4.3.1.tgz
$ cd kafka_2.13-4.3.1
$ KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)"
$ bin/kafka-storage.sh format --standalone -t $KAFKA_CLUSTER_ID -c config/server.properties
$ bin/kafka-server-start.sh config/server.properties
Dockerイメージ1コマンドでの起動
試すだけならDockerのほうが早く、クラスタIDの発行もフォーマットも不要です。GraalVMでネイティブビルドしたapache/kafka-native:4.3.1も配布されていますが、4.3のドキュメントでは実験的でローカル開発・テスト用と位置づけられ、本番利用は推奨されていません。
$ docker run -p 9092:9092 apache/kafka:4.3.1
トピック作成とProducer・Consumerでの疎通確認
ブローカーが上がったら、別のターミナルでトピックを作り、コンソール版のProducerとConsumerで往復させます。Producer側で1行入力するたびに1件のイベントが書き込まれます。
$ bin/kafka-topics.sh --create --topic quickstart-events --bootstrap-server localhost:9092
$ bin/kafka-console-producer.sh --topic quickstart-events --bootstrap-server localhost:9092
>This is my first event
>This is my second event
Consumer側に--from-beginningを付けると、先ほど書いた2件が先頭から読み出されます。この2件は読み出しても消えないので、もう一度同じコマンドを実行すれば同じ結果が返ります。冒頭で述べた「読んでも消えない」がここで確認できます。
$ bin/kafka-console-consumer.sh --topic quickstart-events --from-beginning --bootstrap-server localhost:9092
This is my first event
This is my second event
Kafkaが向くユースケースと選ぶべきでない場面
Kafkaは万能の非同期基盤ではありません。ログ構造という設計が効く領域と、そうでない領域がはっきり分かれます。
向くケース:ログ集約・CDC・サービス間のイベント連携
もっとも相性がよいのは、1つのイベント列を複数の下流が別々の目的で読む構成です。アクセスログを検索基盤とリアルタイム集計と長期保管の3系統へ同時に流す、データベースの変更をトピックへ流して検索インデックスとキャッシュを同期する、といった形が典型です。データベース連携はCDCの3方式とKafka Connectのコネクタ運用を組み合わせる構成が典型で、Kafka内で集計や結合まで済ませたい場合はKafka StreamsかksqlDBのストリームとテーブルを使います。
もう一方の軸は保持期間そのものです。マイクロサービス間の連携をKafka経由にしておくと、受信側の障害中に流れたイベントを復旧後に読み直せます。同期API連携では失われるこの再処理の余地が、Kafkaを選ぶ実質的な理由になることは多いです。
選ぶべきでない場面:単発ジョブのキューと1台構成
メッセージごとの優先度、指定時刻での遅延実行、1件ずつの確認応答と再配信といった要件が中心なら、Kafkaは向きません。4.2で本番利用可能になったShare Groupでレコード単位の分担はできるようになりましたが、優先度付きキューや遅延キューはKafkaの機能ではないままです。この種の要件はRabbitMQやAmazon SQSのほうが素直に実装できます。
ブローカー1台構成も推奨しません。レプリケーション係数が1のクラスタは、ディスク障害がそのままデータ損失になります。それでいてKRaftのメタデータ管理、パーティション設計、コンシューマラグの監視という運用負荷は発生します。冗長構成を組めないうちは、Kafkaを入れる判断そのものを見送るか、マネージドサービスを使うほうが合理的です。
周辺エコシステムとマネージド・互換実装の使い分け
自前でクラスタを立てる以外の選択肢も広がっています。運用の担当範囲と費用の分担点が違うだけで、Kafkaのプロトコルは共通です。
- Amazon MSK … AWS上のマネージドKafka。ブローカー運用をAWSに寄せる。「AWSのKafka」と呼ばれるのは通常これ
- Confluent Platform / Confluent Cloud … Kafkaの開発者らが設立した企業による商用ディストリビューション。ライセンス境界の確認が要る
- Redpanda … C++で書かれたKafka API互換ブローカー。JVMもZooKeeperも使わない
- Apache Pulsar … 計算層と保存層を分離した別系統のストリーミング基盤
ストリーム処理エンジンとの関係も整理しておくと迷いません。Kafkaはイベントを保持して配る側で、Apache Flinkのようなエンジンはそれを読んで計算する側です。競合ではなく、Kafkaを通り道に置き、Flink側がトピックを読み出して計算する形で並べて使います。
よくある質問
Apache Kafkaは何に使われるのですか?
Kafkaはイベントをトピックというログに追記して保存し、複数のシステムへ配るサーバー群です。用途としては、アクセスログやアプリケーションログの集約、データベースの変更をリアルタイムに配るCDC、マイクロサービス間のイベント連携、IoT機器からの計測値の収集が代表例です。共通しているのは「1つのイベント列を複数の下流が別々の目的で読む」構成で、読んでもデータが消えないログ構造がここで効きます。
Kafkaの読み方は何ですか?
Apache Software Foundationの公式ページは英語のみで、カナ表記は示されていません。AWS・Red Hat・NTTデータの日本語ページもいずれも英字の「Kafka」表記のままで、カナは使っていません。日本語圏では一般に「カフカ」と読まれています。なお、検索で作家フランツ・カフカの解説が混ざることがありますが、本記事の対象はApache Software Foundationのソフトウェアです。
KafkaとRabbitMQなどのメッセージキューは何が違いますか?
最大の違いは、読み取ったメッセージが消えるかどうかです。RabbitMQやSQSは確認応答を受けた時点で削除しますが、Kafkaは保持期間(既定168時間)までログに残します。そのため過去のイベントを読み直せますが、優先度付き配信や遅延実行といったキュー特有の機能はありません。判断基準はRabbitMQとKafkaの違いで詳しく比較しています。
Apache SparkやFlinkとKafkaの違いは何ですか?
役割の層が異なります。Kafkaはイベントを受け取って保存し配信する基盤で、SparkやFlinkはそのイベントを読んで集計・結合・変換を行う処理エンジンです。どちらかを選ぶというより、Kafkaをデータの通り道に置き、その上でFlinkやSparkを動かす組み合わせが一般的です。Kafka内で完結する軽い処理であればKafka StreamsやksqlDBで足ります。
AWSのApache Kafkaとは何ですか?
Amazon MSK(Managed Streaming for Apache Kafka)を指すことがほとんどです。Apache Kafkaそのものをマネージドで提供するサービスで、ブローカーの構築・パッチ適用・可用性確保をAWS側が担います。料金体系や自前運用との責任分界点はAmazon MSKの仕組みと料金で整理しています。
Kafkaは無料で使えますか?
Apache Kafka本体はApache License 2.0のオープンソースで、ライセンス費用はかかりません。有償になるのは、Confluent PlatformやAmazon MSKのような商用ディストリビューション・マネージドサービスを選んだ場合と、自前運用のサーバー費用です。Confluent Platformには本体とは異なるライセンスが適用されるコンポーネントが含まれるため、採用前に境界の確認が要ります。