本書では、分散ストリーミングプラットフォームであるApache Kafka(以降、Kafka)を活用したアプリケーションの構築方法を紹介します。
近年ではスマートフォンやIoTなどの普及からシステムで扱うデータが爆発的に増加しています。これらの大量のデータを「ビッグデータ」と呼んで活用することも盛んになってきました。また、システムの構築方法や構造にフォーカスすると、分散アプリケーションが協調するアーキテクチャを採用する企業も増えています。システムのスケーラビリティや開発のアジリティを高める「マイクロサービス・アーキテクチャ」や、リアルタイムかつ非同期にイベントを処理する「イベント駆動アーキテクチャ」などが代表的です。
こういった背景の中で、システム間のデータを橋渡ししつつ大量のデータを処理するために採用されているソリューションがKafkaです。開発のプラットフォームであるクラウドベンダー各社はKafkaのマネージドサービス、または互換性のあるAPIを持ったサービスを提供していることからその人気ぶりが分かります。
しかし、人気が高まっているのにも関わらず日本語で提供されている情報や書籍がまだ少ない状況にあります。特にビジネスの価値を生み出すアプリケーションの構築方法に関する日本語の情報が少ないと感じたことが本書を執筆したモチベーションとなりました。
本書を読むことで、Kafkaの基本概念と実践的なアプリケーションの構築方法が身につくことを目的としています。皆様のシステム開発およびビジネスに本書の知識が少しでもお役に立てれば幸いです。
本書では以下の読者に向けて執筆されています。どれかひとつでも当てはまる場合は本書が役に立つはずです。
・Kafka初学者のアプリケーション開発者・アーキテクト
・リアルタイムのデータ処理に興味のある方
・イベント駆動アーキテクチャやマイクロサービス・アーキテクチャといった分散アプリケーションの開発に取り組もうとしている方
・Kafkaの英語チュートリアルに抵抗感がある方
本書は基本編と応用編の2部で構成されています。
第1章から第4章は基本編です。
・第1章ではKafkaの概要を説明します。Kafkaの機能、代表的なユースケース、構成要素を学びます。
・第2章ではKafkaクラスタの構築とともに、コマンドラインによる基本的なオペレーションを学びます。
・第3章ではKafkaにイベントを送信するKafkaアプリケーションの作成方法を学びます。
・第4章ではKafkaからイベントを受信するKafkaアプリケーションの作成方法を学びます。
第5章以降は応用編です。Kafka特有の機能を活用したアプリケーションの構築方法を紹介します。
・第5章ではKafkaアプリケーションでトランザクションを扱う方法を説明します。整合性を保ったイベント処理を学びます。
・第6章ではKafka Connectを使うことで、データシステムとKafkaを容易に接続する方法を学びます。
・第7章ではKafka Streamsを使うことで、Kafkaのイベントをリアルタイムに処理する方法を学びます。
本書は興味のある章から読んでも理解できる構成になっています。Kafkaに初めて触れる方は第1章から第4章を順に読むことをお勧めします。
本書では基本概念の説明で必要な場合を除き、以下の内容を説明の対象外としています。これらの内容を詳しく知りたい場合は『参考コンテンツ』や別の書籍を参照してください。
・Kafkaの内部アーキテクチャおよび内部実装の詳細
・Kafkaアプリケーションのパフォーマンスチューニング方法
・Kafkaクラスタのデータセンターまたはクラウドへのデプロイ方法
・Kafka商用サービス固有の機能
・コマンドプロンプトまたはターミナルによるコマンドライン操作経験
─Kafkaクラスタをコマンドラインで操作します。
・GitおよびDockerの基礎知識
・少なくともひとつのプログラミングに関する基礎知識
─本書ではKafkaアプリケーションをJavaで実装します。
─ただしPythonやGoといった他の言語でも本書の知識を活用できるように、複雑な知識が要求されるJavaフレームワークは使用しません。
─Java以外のプログラミング言語の扱いやクライアントライブラリについては第1章を参照してください。
本書に掲載しているソースコードはすべて以下のGitLabのリポジトリで公開しています。各章で構築するKafkaクラスタとアプリケーションの完成版が格納されています。なお、利用するプロダクトやライブラリの更新、および誤字修正のため随時更新される可能性があります。
https://gitlab.com/ponzmild/ird-starting-kafka-sample
本書に掲載されているソースコードやコマンドは以下の環境で動作確認を行っています。
・OS ... macOS Monterey (12.4)
・Java ... OpenJDK 11.0.15
・Apache Maven ... 3.8.6
・Docker Desktop ... 4.10.1 (Docker Engine 20.10.17)
・Visual Studio Code ... 1.69.2
コンテナの動作にDocker Desktop互換のソフトウェアを使用する場合、本文中の一部のコマンドが動作しない可能性があります。使用されているソフトウェアのドキュメントを参照し、適宜コマンドを読み替えてください。
本書は以下の書籍およびオンラインコンテンツを参考に執筆しました。本書を呼んで興味を持った内容を深掘りする際にはぜひ参照することをお勧めします。
・書籍 『Kafka』(オライリー・ジャパン)1
・書籍 『Mastering Kafka Streams and ksqlDB』(オライリー・ジャパン)2
・書籍 『Kafka in Action』(Manning)3
・Webサイト『Confluent Developer』4
・Webサイト『Confluent Blog』5
・Udemy『Apache Kafka Series - Learn Apache Kafka for Beginners v2』6
・Udemy『Apache Kafka Series - Kafka Connect Hands-on Learning』7
本書は2020年3月の技術書イベント『技術書典 応援祭』8にて頒布した同人誌『Kafkaをはじめる』を底本にしています。Kafkaは同人誌頒布以降も継続的に機能追加やバグ修正が行われています。また、Kafkaを取り巻く状況、ツール、アーキテクチャのトレンドも変化しています。本書は執筆時点の最新状況を取り込み、内容をアップデートしています。
・本書の内容は執筆時点(2022年7月)までの情報をもとに執筆されています。
・掲載したWebサイト、アプリケーション、サービスは変更される可能性があります。
・本書の内容によって生じる、直接または間接被害について、著者ならびに弊社では、一切の責任を負いかねます。
・本書に記載されている会社名、製品名などは、一般に各社の登録商標または商標、商品名です。会社名、製品名については、本文中では©、®、™マークなどは表示していません。
・コマンドラインのプロンプトは、"$"、"#" で示されます。
・実行結果やサンプルコード内を省略している部分は、"..." で表記します。
・誌面の幅に収まらないコマンドラインの入力は、行末に "\" を入れて改行しています。
本書の執筆の機会および編集に多大なご支援をただきました株式会社インプレスR&Dの山城様には深く御礼申し上げます。また、本書のレビューにご協力いただきました日本アイ・ビー・エム株式会社のKafkaコミュニティの皆様に感謝いたします。皆様から貴重なフィードバックと後押しをいただけたことで無事出版までたどり着くことができました。
最後に私事ではございますが、執筆期間中そばで支えてくれた家族の協力に心から感謝します。ありがとう。
本章ではApache Kafkaの概要について説明します。まずKafkaの機能を概観し、構成要素、APIについて基本を理解しましょう。
Apache Kafkaは「分散ストリーミングプラットフォーム (A distributed streaming platform)」と呼ばれるソフトウェアです1。もともとはLinkedInで開発されたソフトウェアであり、現在はApacheソフトウェア財団で管理されているオープンソースソフトウェア(OSS)です。活発に開発が進められているソフトウェアのひとつでもあり、商用版のKafkaを提供するConfluent社のメンバーを中心に開発が行われています。また、KafkaはScalaとJavaで記述されたソフトウェアです。
Kafkaは「分散ストリーミングプラットフォーム」の名前が指す通り、ストリームデータの扱いに長けています。ストリームデータとは時間とともに次々と発生する無限量のデータです。Kafkaはストリームデータを高スループットかつ低レイテンシでリアルタイムに処理します。
Kafkaは次の3つの機能・役割を持ったソフトウェアです。
Kafkaは、システム間でやりとりするデータ(イベント)を中継します。イベントがKafkaを中継することでイベントを送受信するシステム同士は互いの物理的な位置や処理タイミングを知る必要がありません。この特徴により、Kafkaを中継するシステム同士を疎結合に保つことができます。
また、Kafkaのイベント送受信形態は一般的にPublish/Subscribe型と呼ばれます。この形態は送信側と受信側のシステムが1対多の関係になります。同じイベントを複数の受信側のシステムで受け取ることが可能です。
イベントを送受信するアプリケーションから見ると、Kafkaはイベントを永続化するストレージの役割を担います。Kafkaに送信されたイベントはログファイルに追記することで永続化されます。ログファイルはKafkaが稼働するサーバー(Broker)のファイルシステムに書き込まれます。アプリケーションがKafkaからイベントを受信してもログファイルにイベントが残るため、何度でもイベントを再生することが可能です。
Kafkaはイベントだけでなく、受信側のシステムのイベント読み出し位置(Offset)も永続化します。読み出し位置を永続化することでイベントを受信するシステムは障害発生時も処理を途中から再開できるため、耐障害性の高いシステムとなります。
ただしイベントの永続方法はログファイルの末尾への追記となるため、データベースのように直接イベントを更新または削除することができません。イベントを更新・削除する場合は、送信側のシステムから更新・削除イベントをKafkaに送信して、受信側で別途処理する必要があります。
Kafkaはリアルタイム処理のためのAPIを提供します。このAPIを使用したアプリケーションを構築することで、リアルタイムのイベント処理を可能にします。ストリーム処理の一例として、イベントの集約、フィルター、情報の付加(エンリッチメント)を実行します。さらに、処理したイベントを再度Kafkaに送信することで他のシステムから加工済みのイベントを処理できます。
Kafkaがなぜ1.1で説明した機能・役割を持っているのか、またどんなユースケースに適しているのかを知るためには、Kafkaが生まれた背景を知ることが重要です。
KafkaはLinkedInの課題を解決するために開発されました。Kafka開発の切っ掛けとなったのは、ユーザアクティビティを追跡するシステムと、サーバのメトリクスを管理するモニタリングシステムの問題です2。
2つの独立したシステムはデータを他のシステムから使用するインターフェイスを持っていましたが、バッチ処理でデータを連携していました。そのため、リアルタイムにデータを利用できないという課題がありました。2つのシステムのデータを組み合わせて相関関係をリアルタイムに分析することも困難でした。また、ユーザアクティビティを追跡するシステムのデータはひとつの送信先しかサポートしておらず、複数システムから使えないという課題もありました。それぞれの課題は当時のオープンソースベースのソリューションで解決できないか検討されています。しかし、LinkedInが扱う規模のデータを処理すると問題が発生し、データの増加に伴うシステムのスケーラビリティに課題がありました。
以上の課題を解決するため、Kafkaは次の目標を達成するソフトウェアとして開発されました。
・データを生成(送信)するシステムと、データを消費(受信)するシステムを分離する
・同じデータを複数のシステムで消費できるようにするため、データを永続化する
・データを高スループットのために最適化する
・データストリームの成長に合わせて、システムを水平にスケールできる
これらの目標を達成することで、Kafkaは単なるメッセージングシステムにとどまらないソフトウェアとなりました。
KafkaはLinkedInが解決した課題だけでなく、数多くのユースケースに適用可能です。例として次のユースケースで多く利用されています。
・システム間連携のデータハブ
・受信側の過負荷を抑える処理バッファ
・ユーザーアクティビティの追跡
・データウェアハウスのためのデータパイプライン
・ログの集約・フォワーディング
・メトリクスの収集
・バックエンドシステムのデータを要件に応じて別システムのデータストアに複製(Event Stream Projection)
・複数ドメイン間のデータ共有(Data Mesh)
・イベントソーシングやCQRS3のためのイベントストア
・サービス間連携のオーケストレーション(Sagaパターン)
・モノリスからサービスを分割するためのデータ移行レイヤー(Stranglerパターン)