Apache Kafka®の簡単な説明

<font color="Grey">*[Apache Kafka® simply explained](https://aiven.io/blog/kafka-simply-explained)の翻訳です。*</font>

2022年7月5日

# Apache Kafka® の簡単な説明

Apache Kafkaの学習は難しくありません。Apache Kafkaの基礎をやさしく解説します。

## Apache Kafka®をeコマースプロジェクトを例に簡単に解説


Apache Kafka®は業界で広く使用されていますが、学習曲線は険しく、この技術の構成要素を理解することは困難な場合があります。そのため、この記事ではApache Kafkaの基本を簡単に説明することを目的としています。


### Apache Kafkaの概要


Apache Kafkaは**イベント・ストリーミング・プラットフォーム**であり、分散型、スケーラブル、高スループット、低レイテンシーで、非常に大規模なエコシステムを持っている。


簡単に言えば、**複数のシステム、複数のマイクロサービス、またはその他の作業モジュール間で**メッセージの転送を処理するプラットフォーム**です。これは単なるフロントエンド/バックエンドアプリケーションでも、IoTデバイスのセットでも、その他のモジュールでも構わない。


Apache Kafkaプラットフォームは**分散型**であり、複数のサーバーに依存し、データは複数の場所に複製される。


スケーラブル**で、必要なだけサーバーを持つことができます。小さく始めて、システムの成長に合わせてサーバーを増やすことができます。これらのサーバーは、1日に何兆ものメッセージを処理することができ、最終的にはペタバイトのデータをディスク上に永続的に保存することができます。


Apache Kafkaの素晴らしいところは、**コミュニティ**と**このテクノロジーを取り巻く幅広いエコシステム**にある。これには、さまざまなプログラミング言語で利用可能なクライアント・ライブラリや、Kafkaを既存の外部システムと統合するためのデータ・コネクタのセットが含まれる。したがって、Apache Kafkaを使い始めるために車輪を再発明する必要はありません。代わりに、すでに同様の問題を解決した素晴らしい開発者の仕事に頼ることができます。


### Apache Kafkaが使用されている場所


Apache Kafkaのニーズがどこから来ているのかを理解するために、ある製品の例を見てみましょう。


あるeコマース・プロジェクトを立ち上げることにしたとしよう。プロジェクトに取りかかったとき、おそらくMVP（minimal viable product）の段階で、私たちはすべてのサブシステムを1つのモノリスとして隣り合わせにしておくことにしました。そのため、当初からフロントエンドとバックエンドのサービス、そしてデータストアは密接に相互接続していました。


![シンプルなモノリスの図 - データベースは、フロントエンド、配送、支払い、注文と呼ばれるサービスに接続されており、それぞれが他のサービスにも接続されている](https://cdn.sanity.io/images/sczeoy4w/production/0785b64b6bbaf8c47acded3cdd3adb25a9553392-1600x1100.png?q=80&fit=min&auto=format&dpr=1.5)


これは理想的とは言えないかもしれないが、最初のうちはこのアプローチは効果的で、少数のユーザーと限られた機能性であればうまくいくだろう。


しかし、ひとたび規模を拡大し、より多くのモジュールを追加し始めると（例えば、レコメンデーション・エンジンや通知サービスなどを導入する）、現在のアーキテクチャーや情報の流れはあっという間に完全なカオスとなり、サポートや拡張が困難になります。また、開発チームが大きくなるにつれ、この製品のデータフローに一人の人間がついていけなくなるでしょう。


![複雑なモノリスの図-データベースはたくさんのサービスに接続され、さらにそのサービスは互いに接続されている。この図を理解するのは不可能だ](https://cdn.sanity.io/images/sczeoy4w/production/9fbf16ab7e56d9dec53de715f9f115ac6828d098-1600x1100.png?q=80&fit=min&auto=format&dpr=1.5)


そのため、最終的には、モノリスを、明確で、合意され、文書化された**通信インターフェース**を持つ**独立したマイクロサービス**のセットに分割する方法について、厳しい会話をする必要があります。


さらに重要なことは、私たちの新しいアーキテクチャは、ユーザーが最新の購入に基づいた有意義な推奨を得るために明日まで待つ必要がないような**リアルタイムのイベント**に製品が依存することを可能にしなければならないということです。


そして、これは多くのことを要求している。このようなイベント処理を導入することは、膨大な量のオペレーションであり、障害に強い必要がある。


幸運なことに、これらはまさにApache Kafkaが助けてくれる課題だ。Apache Kafkaは、データフローをほぐし、**リアルタイムデータを扱う**方法を簡素化し、**サブシステムを切り離す**ことに優れています。


### Apache Kafkaの考え方


Apache Kafkaがどのように機能し、どのように効率的に作業できるかを理解するには、Apache Kafkaのデータに対する考え方について説明する必要がある。


Apache Kafkaのアプローチはシンプルだが賢い。Apache Kafkaは、静的なオブジェクトや、集約されてデータベースに保存される最終的な事実の形でデータを扱うのではなく、**継続的に到着するイベント**によってエンティティを記述する。


例えば、私たちのeコマース製品では、販売する商品のリストがあります。それらの在庫状況やその他の特徴は、以下のように数値としてデータベースに表示することができます。


![テーブル。列のタイトルは、Name、Available、Sold、Searchedです。1行目はノートパソコン、50、20、30。2行目は電球、15、3、5。3行目はパズル、6、2、7。](https://cdn.sanity.io/images/sczeoy4w/production/5631a94dcfca6d0071a322d02b39507f8d3be25f-1500x468.png?q=80&fit=min&auto=format&dpr=1.5)


これで貴重な情報、最終的な集計結果が得られた。しかし、どのような情報を保存するかは、将来の洞察の計算をカバーするのに十分なように、慎重に計画する必要がある。将来何が起こるかわからないので、どのデータを長期保存し、何を捨てても安全かを予測するのは非常に難しい。


Apache Kafkaは、集約されたオブジェクトの特性を保存する代わりに、このデータをイベントの流れとして捉えることを提案している：


![イベントはタイムラインに沿って発生する。イベント1は顧客55がノートパソコンを注文、イベント2は顧客12が電球を検索、イベント3は顧客55にノートパソコンを発送、イベント4は顧客12が電球を5個注文](https://cdn.sanity.io/images/sczeoy4w/production/13f52fb22318974c68c4f1fb10eac1176597984a-1600x734.png?q=80&fit=min&auto=format&dpr=1.5)


このフローは製品購入の完全なライフサイクルを示している。そして、集約された最終データを見る代わりに、状態の変化を観察する。


必要に応じて、イベントを再生することもできる。最初から始めることもできるし、ある時点に移動することもできる。


しかし、イベントを何度も再生し、必要な指標を計算し、製品や帆に関するさまざまな質問に答えることができます。


このタイプのアーキテクチャは、実際には**イベント駆動アーキテクチャ**と呼ばれ、次のセクションでは、Apache Kafkaがこのようなアーキテクチャにどのように適合するかを見ていきます。


### Apache Kafkaがイベントを調整する方法


Apache Kafkaクラスタはデータの移動を調整し、受信メッセージを処理する。Apache Kafkaは**push-pullモデル**を採用しています。つまり、一方の側にはメッセージを作成してクラスタにプッシュするプロセスがあり、それらは **producers** と呼ばれます。もう一方の側には、メッセージをプルし、読み、処理する **消費者** がいます。


![プロデューサーAとプロデューサーBはKafkaクラスタにメッセージを送る。クラスタ内にはメッセージのタイムラインがある。データベースと電話アプリの2つのコンシューマーが、クラスターからメッセージを読む](https://cdn.sanity.io/images/sczeoy4w/production/c0db44fb8695a8b3d3d0c32abcdeda887d121a57-1600x602.png?q=80&fit=min&auto=format&dpr=1.5)


プロデューサーとコンシューマーは、あなたが書いてコントロールするアプリケーションだ。プロデューサーとコンシューマーは必要な数だけ持つことができる。


eコマースの例を見てみると、プロデューサーはフロントエンド・アプリケーション、ウェブ・アプリケーション、モバイル・アプリケーションの一部になることができる。ユーザーのアクションを観察し、情報をパッケージ化し、イベントをクラスタに送信する。コンシューマーは、バックエンドモジュール（この例では、通知、配送、レコメンデーションサービス）を担当するサブシステムに接続することができる。


重要なのは、プロデューサーとコンシューマーは異なる言語、異なるプラットフォームで記述することができ、お互いの存在を全く知らないということだ。  

あるプロデューサーの活動を停止させ、他のプロデューサーの活動を追加することができる。その一方で、消費者はメッセージが他のエンティティによって作られたものであることを気にしないし、そのことにさえ気づかないだろう。


コンシューマーが壊れても、プロデューサーは問題なく作業を続け、新しいメッセージを生成してApache Kafkaに送信し、それらのメッセージは永続ストレージに保存される。コンシューマーが復旧すると、最後に読み込んだメッセージ情報がプラットフォームに永続化されるため、コンシューマーは最初から再スタートする必要はない。


従って、プロデューサーとコンシューマーの作業の間には**同期が期待されない**。そしてこれが、システムのデカップリングに役立っているのだ。


さて、メッセージがどこから来て、誰が後で読むのかがわかりましたが、Kafkaクラスタ内部ではどのように整理されているのでしょうか？


### トピックとメッセージ


Apache Kafkaでは、一連のメッセージを**トピック**と呼ぶ。トピックは抽象的な用語で、これについては後ほど説明するが、要するに、ものが物理的にどのようにディスクに格納されているかということではなく、物事を単純化するためにどのように考えるかということだ。


データベースのテーブルと同じように、異なるタイプのイベントを記述するトピックを必要なだけ持つことができる。先ほどの例に戻ると、製品購入のライフサイクルを記述した情報を持つトピック、ユーザー登録イベントを記述した別のトピック、システムの健康状態イベントを記述したトピックを持つことができます。


![3つのトピックが表示されています。トピック 1 には、ユーザ登録イベントが含まれます。トピック 2 には製品関連イベントが含まれます。トピック3にはアプリケーションのイベントが含まれています](https://cdn.sanity.io/images/sczeoy4w/production/870486dab3c1fb2d1f8a818d5cb96fa24c7eb4c8-1600x1096.png?q=80&fit=min&auto=format&dpr=1.5)


データは継続的にトピックに流れ込みます。アプリケーションが動作している限り、新しいユーザーが登録され、新しい商品が購入されます。


メッセージには順序があります。各レコードの位置はシーケンス番号で識別され、これは**オフセット**として知られています。


また、メッセージは不変であり、後からレコードを変更することはできない。これは完全に論理的である。例えば、誰かが私たちのショップで商品を購入し、そのアクションのイベントを記録したとします。後で過去にさかのぼってその事実を変更することはできない。もし顧客が商品を返品すると決めたら、これは新しいイベントとなる。このように、新しいイベントをトピックに送ることで、オブジェクトの状態を変更する。


Apache Kafkaでは、他の多くのキューシステムとは異なり、**消費されたメッセージはキューから削除**されず、破棄されません。その代わり、必要であれば、複数のコンシューマーが何度も読み込むことができる。実際、これは非常に一般的なシナリオであり、トピックからの情報は、異なるニーズのために複数の消費アプリケーションによって使用され、異なる視点からデータにアプローチします。


### ブローカーとパーティション


Kafkaクラスターが複数のサーバーで構成されていることは既に述べた。これらのサーバーは**ブローカー**と呼ばれる。そしてトピックはその上に保存される。トピックには何百万、場合によっては何兆ものイベントが含まれる。そのため、これらの長いレコード列をどのようにサーバーに保存するかを考える必要がある。


トピックというのは抽象的な言葉だと前に言ったのを覚えているだろうか。トピックそのものは、一つのサーバーに全体として保存される物理的な有形物ではない。  

トピックを1つのデータとして1台のマシンに保存しておくことは、おそらく合理的でも実現可能でもないだろう。おそらくいつか、トピックのサイズはサーバーのメモリーを超えてしまうだろう。だからこそ、垂直方向ではなく水平方向に拡張することが非常に重要なのだ。


そのために、トピックを複数のマシンにまたがる複数のチャンクに分割する。これらのチャンクは**パーティション**と呼ばれる。  

各パーティションは技術的には**メッセージのログ**である。


![プロデューサーは商品関連のイベントを送信しており、それらは3つの異なるパーティションに分割される。テレビとヘッドホンのイベントはパーティション1、映画とゲームアイテムのイベントはパーティション2、電話と無線LANステーションはパーティション3にある](https://cdn.sanity.io/images/sczeoy4w/production/40b7bd841686ce166e1e718b5ca8daf543fe736d-1600x962.png?q=80&fit=min&auto=format&dpr=1.5)


パーティションは独立したエンティティです。各パーティションは独立して、それぞれの値のオフセット番号を保持します。つまり、オフセットは1つのパーティション内でのみ意味を持ち、パーティションをまたいでもオフセット同士の関連性はありません。


以前、プロデューサーがトピックに書き込むと言ったのは、プロデューサーがパーティションの集合に書き込むという意味だ。そして、コンシューマーはパーティションのセットから読み出す。


舞台裏では、コンシューマーとプロデューサーは複数のパーティションを扱う方法を知っている。


### レプリケーション


これまで、トピックについて、トピックがパーティションに分割され、ブローカーにまたがる方法について話してきた。もう一歩深く潜って、レプリケーションについて話そう。


高可用性を維持し、データ損失を防ぐために、Apache Kafkaはブローカー間でデータをレプリケートする。レプリケーションはパーティションレベルで行われる。特に、各ブローカーは複数のパーティションを保持する。これで、いずれかのブローカーに問題が発生した場合、そのパーティションのデータを別の場所から取得できる。


![A、B、Cの3つのブローカーがあり、それぞれ2つのパーティションを持っている。パーティションの内容は異なるが、ブローカーBとブローカーCは1つのパーティションをレプリケートしている - レプリケートされたパーティションのイベントは両方のブローカーで同じである](https://cdn.sanity.io/images/sczeoy4w/production/f00bbb91d4a7637f72e62bc512bc6e6eb2d6376f-1600x634.png?q=80&fit=min&auto=format&dpr=1.5)


### Apache Kafka コネクター


これまで、Apache Kafkaのコンセプトとビルディング・ブロックをたくさん取り上げてきた。もう1つ、少し高度だが、アプリケーションとApache Kafkaの接続を簡単にする概念を紹介したい。


Apache Kafkaは伝送メカニズムである。非常に一般的なシナリオは、データがソース・テクノロジですでに利用可能であるか、またはターゲットとなる宛先にプッシュする必要がある場合です。そこで、Apache Kafka Connectが非常に役に立つ。これは、外部データソース（PostgreSQL®、OpenSearch®、その他のデータベースやツールなど）を統合するために使用されるコネクタを記述するためのツールです。これらのビルド済みコネクタは複数のプロジェクトで使用でき、実際、その多くはオープンソースでコミュニティによってサポートされている。また、まだ存在しないコネクタがあれば、自分で作成することもできます。


### 次のステップ


Apache Kafkaがどのように機能するのか、ご理解いただけたと思います。もっと深く知りたい方は、Kafkaの旅の詳細なトピックを探った以下の記事をご覧ください：


* [Apache Kafkaクラスタにデータを供給するためのデータジェネレータ](https://developer.aiven.io/docs/products/kafka/howto/fake-sample-data.html)の作成方法、
* [kcat - コマンドラインからApache Kafkaを操作するための非常に便利なユーティリティ](https://developer.aiven.io/docs/products/kafka/howto/kcat.html)の使い方、
* [Kafkaクラスタに来るデータの構造を調整するためのKarapaceスキーマレジストリ](https://aiven.io/blog/what-is-karapace)の適用方法、
* [Apache Kafka®を使用してデータベース技術を移行する方法](https://aiven.io/developer/db-technology-migration-with-apache-kafka-and-kafka-connect).


また、より詳細な情報やリソースについては、[以前の投稿「Apache Kafka®とは](https://aiven.io/blog/what-is-apache-kafka)を参照してください。