Apache Kafkaは、分散型イベントストアおよびストリーム処理プラットフォームである。Apacheソフトウェア財団が管理するオープンソースのシステムで、JavaとScalaを用いて実装されている。このプロジェクトは、リアルタイムのデータフィードを処理するための、統一された高スループット・低遅延のプラットフォームを提供することを目的としている。Kafka Connectと呼ばれるフレームワークを用いることにより、外部システムと接続しデータのインポート/エクスポートを行うことができるほか、ストリーム処理を行うアプリケーション向けのKafka Streamsライブラリが提供されている。通信の効率化を行うため、KafkaはTCP上でバイナリ形式による通信を行い、また「メッセージセット」と呼ばれる概念を導入し複数のメッセージをまとめて送受信することを可能にしている。これらの工夫により、Kafkaは「より大きなネットワークパケット、より大きなシーケンシャルなディスク操作、連続したメモリブロック(中略)を実現し、莫大な数のランダムなメッセージを線形に書き込むことができる」と主張する。

## 歴史

Kafkaは元々LinkedInで開発され、その後2011年初めにオープンソース化された。ジェイ・クレプス、ネーハ・ナルケデ、ジュン・ラオによって共同で開発された。2012年10月23日にApache Incubatorから卒業した。このシステムの名称はフランツ・カフカに由来するが、クレプスはその理由として、Kafkaが「書くことに最適化されたシステム」であり、また彼がカフカの作品が好きだったためと語っている。

## アプリケーション

Apache Kafkaはコミットログをベースにしており、ユーザーはそれをサブスクライブして、任意の数のシステムやリアルタイムアプリケーションにデータを公開することができる。Kafkaの採用例として、Uberにおける乗客とドライバーのマッチング管理、ブリティッシュガスのスマートホームサービスにおけるリアルタイム分析および予知保全の提供、LinkedIn全体における多数のリアルタイムサービスの実行などがある。

## アーキテクチャ

Kafkaは、「プロデューサー」と呼ばれる任意の数のプロセスから送られてくるKey-Valueメッセージを保存する。データは、異なる「トピック」内の異なる「パーティション」に分割することができる。パーティション内では、メッセージはオフセット(パーティション内でのメッセージの位置)の順に記録され、タイムスタンプとともにインデックス化されて保存される。「コンシューマー」と呼ばれる他のプロセスは、パーティションからメッセージを読み取ることができる。ストリーム処理については、KafkaはStreams APIを提供しており、Kafkaからデータを取り出して、何らかの計算結果をKafkaに書き戻すJavaアプリケーションを書くことができる。また、Apache Kafkaは、Apache Apex、Apache Beam、Apache Flink、Apache Spark、Apache Storm、Apache NiFiなどのストリーム処理システムとも連携させることができる。

Kafkaは1台以上の「ブローカー」と呼ばれるサーバーから構成されるクラスタ上で動作し、全てのトピックのパーティションがクラスタノードに分散される。さらに、パーティションは複数のブローカーに複製されている。このアーキテクチャにより、Kafkaは大量のメッセージストリームをフォールトトレラントな方法で配信でき、Java Message Service (JMS)やAdvanced Message Queuing Protocol (AMQP) などの従来のメッセージングシステムの一部を代替できるようになった。バージョン0.11.0.0でトランザクション書き込みが実装され、Streams APIを用いたexactly-onceなストリーム処理が実現可能となった。

トピックには通常のトピックとコンパクト化されたトピックの2種類がある。通常のトピックにおいては保持時間または容量上限を設定することができる。指定された保持時間よりも古いレコードが存在する場合やパーティションの容量上限を超えた場合には、ストレージ領域を確保するために古いデータが削除される。コンパクト化されたトピックでは、あるキーを持つメッセージが送られてきた際に、同じキーを持つメッセージの更新としてそのメッセージを扱う。メッセージは期限切れや容量超過などの理由により削除されることはなく、特定のキーに対しNULL値を持ついわゆるtombstone(墓標)メッセージを書くことで初めて削除される。

Kafkaには、5つの主要なAPIがある。

- メッセージの公開を行うためのProducer API
- トピックをサブスクライブし、メッセージのストリームを処理するためのConsumer API
- 既存のアプリケーションにトピックをリンクさせることができるConnector API
- 入力されたストリームのメッセージを変換し別のストリームとして出力するためのStreams API
- トピック、ブローカー、およびその他のKafkaオブジェクトを管理するためのAdmin API

Consumer APIとProducer APIは、基盤となるメッセージングプロトコルによってKafkaのコア機能から切り離されている。これにより、Consumer APIとProducer APIと互換性のあるAPIをJava以外の言語でも性能を保ったまま実装することができる。Apache Kafkaプロジェクトは、このようなサードパーティ製のAPIのリストを管理している。

## Kafka API

### Connector API

Kafka Connect(またはConnector API)は、バージョン0.9.0.0で追加された他のシステムとの間でデータをインポート/エクスポートするためのフレームワークである。Connectフレームワーク自体は、他のシステムからデータを読み書きするための実際のロジックが実装された、いわゆる「コネクター」を実行する。Connector APIは、カスタムコネクタを構築するために実装しなければならないプログラミングインターフェースを定義している。一般的なデータシステム向けのオープンソースおよび商用のコネクターは、すでに多数提供されている。しかし、Apache Kafka自体には、実用可能なコネクターは含まれていない。

### Streams API

Kafka Streams(またはStreams API)は、Javaで記述されたストリーム処理ライブラリである。Kafka 0.10.0.0リリースで追加された。このライブラリにより、拡張性、伸縮性、耐障害性に優れたステートフルなストリーム処理を行うアプリケーションを開発できる。主なAPIはストリーム処理用のDSLで、フィルタ、マップ、グループ化、ウィンドウ、集約、結合、テーブルの概念などの一般的なストリーム操作を提供する。より詳細なストリーム処理の実装のためにProcessor APIも用意されており、DSLとProcessor APIを併用して処理を記述することもできる。ステートフルなストリーム処理のために、Kafka StreamsはRocksDBを使ってローカルな各演算子の状態を保持する。RocksDBはディスクへの書き込みが可能なため、保持される状態は利用可能なメモリ容量よりも大きくなる可能性がある。また、耐障害性の観点から、ローカルのステートストアへの更新はすべてKafkaクラスタのトピックに書き込まれる。このため、これらのトピックを読み込むことで状態を再現し、すべてのデータをRocksDBに送り込むことができる。

## バージョンの互換性

バージョン0.9.xまでのKafkaブローカーは、古いクライアントとのみ後方互換性をもつ一方、バージョン0.10.0.0以降では、ブローカーは新しいクライアントと前方互換性もある。新しいクライアントが古いブローカーに接続した場合、ブローカーがサポートする機能のみを使用することができる。Streams APIについては、バージョン0.10.1.0から完全な互換性がある。0.10.1.0のKafka Streamsアプリケーションは、0.10.0や古いブローカーと互換性はない。

## パフォーマンス

エンドツーエンドのパフォーマンスを監視するには、ブローカー、コンシューマー、プロデューサーのメトリクスを追跡する必要があり、さらにKafkaがコンシューマー間の調整に使用しているZooKeeperも監視する必要がある。現在、Kafkaのパフォーマンスを追跡するためのモニタリング・プラットフォームがいくつか存在する。これらのプラットフォームに加えて、Kafkaデータの収集は、JConsoleを含む一般的にJavaにバンドルされているツールを使用して実行することもできる。