世界を動かす技術を、日本語で。

なぜApache Kafkaは作られたのか?

概要

  • Apache Kafka は、もともと LinkedInのデータ統合問題 を解決するために開発された分散型メッセージングシステム。
  • 旧システムの 非効率性・拡張性不足 が、Kafka誕生の直接的な動機。
  • スキーマ管理・リアルタイム性・高い耐障害性 が主要な設計要件。
  • Kafkaは データの可用性・統合性・自動化 を実現し、組織全体のデータ活用を加速。
  • スキーマ設計と所有権移譲 が最終的な成功の鍵。

Kafka誕生の背景とLinkedInの課題

  • 2012年当時のLinkedIn は、サイトアクティビティデータの統合に苦戦
    • データ利用例:不正検知、求人マッチング、ML学習、基本的なWeb機能、DWHへの取り込み
  • 既存インフラは 堅牢性に欠け、手動作業が多発
    • バッチ処理によるDWH連携パイプライン
    • Zenossを用いたリアルタイム監視パイプライン
  • 共通課題
    • 手作業・保守負担の大きさ
    • データカバレッジ不足とバックログの増大
    • システム間の統合性欠如、複数データの統合困難

旧システムの根本的な問題点

  • スキーマ解析 :数百のXMLスキーマ、Hadoop等下流システムとの非互換
  • 脆弱性 :パイプライン障害がWeb機能に直結
  • スキーマ進化の困難さ :下流影響を考慮した変更が困難、チーム間連携不足
  • リアルタイム性の欠如 :指標取得に数時間のラグ
  • データ分断 :運用指標とアクティビティデータの統合不可
  • 分析の制限 :長期間の運用指標分析不可
  • 単一宛先問題 :用途拡大に追従できないデータ配送

LinkedInの新システム要件

  • 堅牢なパイプライン :標準APIによる信頼性
  • スケーラビリティ :水平拡張可能な構成
  • スキーマ管理 :後方互換性のある契約
  • 高いファンアウト :多宛先へのデータ配送
  • リアルタイム性 :秒単位の低遅延
  • プラグ&プレイ統合 :新規ソース/シンクの容易な追加
  • 所有権の移譲 :データ作成チームへの責任移管
  • 読者・書き手の分離 :データバックログ耐性

Kafkaによる解決とその特徴

  • 分散設計・レプリケーション・耐障害性 による堅牢化
  • パーティションによるスケーラビリティ、コモディティハードウェアでの拡張
  • ロックフリーなログ構造 で高スケール読込を実現
  • ディスクバッファリング により読者遅延の影響排除
  • リアルタイム性 の大幅向上(初期10秒→現在は数秒以下)

スキーマ管理とデータ統合の進化

  • XMLからApache Avroへ移行 :データサイズ7分の1、さらに3倍圧縮
  • スキーマレジストリの先駆け開発 :全バージョンの履歴管理とID付与
  • 後方互換性モデル :プログラム的なスキーマ変更チェック、BREAK防止
  • 単一スキーマ戦略 :上流・下流間で統一、手動変換作業の排除
  • スキーマオンライト :Kafka着信時にクリーン化、全用途への即時利用可能化
  • コードレビュー必須化 :スキーマ変更時の全関係者承認、ドキュメント化促進

所有権移譲と組織的変革

  • パイプラインチームからデータ作成チームへ責任移管
  • 下流システムとの合意形成 :全チーム共同でスキーマ策定
  • スキーマ管理体制の明確化 :組織全体のデータ品質向上

結論

  • Kafka + スキーマ管理 は、 大規模データ統合とリアルタイム処理 のための最適解
  • データ統合・スキーマ設計・所有権移譲 の重要性
  • LinkedIn事例が示す、 組織横断的なデータ活用基盤構築の成功モデル

Hackerたちの意見

企業向けじゃないところでKafkaを使った失敗をしたことがあるけど、etcdの問題に似てるよね。サービスを提供するのに必要な時間より、etcdを動かすのにもっと時間がかかる感じ。

以前、クライアントのためにKafkaクラスターのセットアップや運用を手伝ってたんだけど、彼らがKafkaを必要とする理由がいつも最初の質問だったんだ。結局、誰からもいい答えはもらえなかった。Kafkaが役立つことは間違いないけど、適切な状況での話ね。でも、その状況は「キューが必要」っていうのじゃない。キューが必要なら、RabbitMQとかZMQ、Redis、SQS、名前付きパイプ、Kafka以外の何でも使えばいい。Kafkaができないわけじゃないけど、余計な手間をかけてるだけだよ。

分散システムを運用してるなら… それは簡単じゃないよ。特にAWSではね。AWSは本当に両刃の剣だよ。分散システムをすぐにセットアップするためのチュートリアルはたくさんあるけど、ノードの信頼性は全然ないし、ネットワークもあまり信頼できない。コストも安定しないし、管理も大変。長い目で見ると頭痛の種が増えるよ。

https://s2.dev で作ってるもの、気に入るかもね :)

Kafkaは、少なくとも名前は的を射てるよね。

スタートアップの創業者だけど、試してみたら、なんか膨れすぎてる感じがした(Javaだし!)。官僚的で、必要以上に複雑だと思う。90%のユースケースにはRedisのキューとかZMQで十分だと思う。超パフォーマンスが求められるハイパースケールなアプリケーション(例えば、リアルタイムトレーディングや大規模なストリーミングプラットフォーム)でこそKafkaが必要になるんじゃないかな。

Redpanda試したことある?

もしこの手のRedisキュー(https://redis.io/glossary/redis-queue/)を使ってるなら、PUSH/POPとファンアウトの違いで、Kafkaが作られた問題とは全然別の問題に取り組んでることになるよ。記事にも書いてあるけど、ファンアウトは重要な設計特性だよね。今は「Redis Streams」もあるけど、当時はなかったし、耐久性やクラスターの話もあまり良くないと思う。だから、ある程度までは使えるかもしれないけど、将来的にシステムがどうなるかによっては一般的には適してないかも。RedPandaみたいにJavaなしでKafkaを使えるものもあるけど、もしパーティショニングを気にせずに単一ノードで動かせるなら、できるだけそうした方がいいよ。複数のパーティションを追加すると、順序を考えるのが難しくなってくるし、メッセージキーみたいなもので対処できるけど、制限があってホットスポットやスケーリングのボトルネックにつながることもある。PUSH/POPベースのシステムも、少なくとも一度は保証してくれないし(Redisには「pop+push」みたいな、単一のコンシューマーが管理する別のリストに移動する機能があるけど、スケールアウトするのが難しくなりそうだよね…)。

なんか膨れすぎてる感じがした(Javaだし!) それって具体的にJavaのどこが膨れすぎてると感じたの?Javaの言語やランタイムが特に膨れすぎてるとは思わないから、Javaソフトウェア周りでよく見かけるプラクティスや原則のことを指してるのかな?

必要とされるのに「ハイパースケール」である必要はないよ。ハイパースケールの定義がかなり違うなら別だけど。数千台のサーバーからのアクセスログがあれば、どんな単一インスタンスのサービスでも限界を超えるし、Kafkaはそのワークロードにはすごく合ってる。

おそらく、超パフォーマンスが求められるハイパースケールのアプリケーション(例えば、リアルタイムトレーディングや大規模ストリーミングプラットフォーム)でこそKafkaが活躍するんだろうね。Javaの人たちは、仕事の安定のために新しいことを学びたくないから、Kafkaを使ってるけど、今はもっと速くて互換性のある代替品があるのに。Redpandaを使う方が、Kafkaを使い続けてリソースを食い潰しながら文句を言うよりいいよね。AWSに何十万も取られてるのに。

Kafkaにイベントを発行すると、それが「外に出る」形になって、失われないことが保証されるし、データウェアハウスを含む興味のある消費者が自分のペースで処理できるようになる(保持期間は通常72時間くらいだけど)。私たちにとって、Kafkaのトピックやスキーマは、gRPCのIDLと同じくらいAPIの一部なんだ。Redisや0MQのようなものは、同じサービスのインスタンス間の内部調整にはもっと適していると思うし、特定のコンシューマを意識したプロデューサーには特にね。

全然同意できない… ZMQに行くと、Kafkaで無料でもらえる多くのことを自分で処理しなきゃいけなくなる。ビッグデータの問題があるなら、運が必要だよ。結局、同じことをまた最初からやり直す羽目になる。

もし「技術が重い」とか「Javaについてはミームレベルの知識しかない」みたいなスタンスを持ってるなら、技術的な決定を任されてないことを願うよ。

LIにいた時にこれに取り組んでたけど、その時の大きな売りはメッセージのリプレイ可能性だったと思う。でも、Pub/Subで得られるようなものに近かったかな。複数のクライアントが同じメッセージをリスニングして、自分の目的で処理できるから、同じキューを使ってもそれぞれのクライアントが好きなように処理できたんだ。

必要なときにメッセージを後から再生できる能力があることだね。少なくとも、これが私たちがシンプルなキューの代わりにKafkaを使うことにした理由だった。すでに処理したデータの新しいコンシューマタイプを作るときや、後で必要になるけど今は優先順位の関係で作れないときに役立ったよ。

ここでhttps://nats.ioを使ってる人いる?いい評判を聞いたことがあるんだけど、nats.ioとKafkaの比較について聞いてみたいな。

Kafkaの経験はないけど、NATSは本当に素晴らしいよ。使うのがすごく楽しいし、全ての面で最高だね。 https://www.synadia.com/blog/nats-and-kafka-compared

パフォーマンスと信頼性について、彼らのフィールドCTOには本当に腹が立ったよ。基本的に、彼らのベース製品(NATS)はパフォーマンスが高いけど、信頼性とトレードオフになってる。だから、NATSにJetstreamを追加して信頼性を得るけど、純粋なNATSのパフォーマンス数値を使ってる。MongoDBに同じことをされたから、こんな不誠実なマーケティングをする技術とは二度と関わりたくない。

NATS、Kafka、他の比較がここにあるよ: https://docs.nats.io/nats-concepts/overview/compare-nats

NATSはすごくいいよ。ただ、コアNATSとJetstreamを区別することが大事だね。コアNATSは一時的なメッセージブローカーなんだ。クライアントがサーバーにどのトピックのメッセージが欲しいかを伝えて、プロデューサーが発行する。NATSがルーティングを担当するんだけど、誰も聞いてなかったらメッセージはどこにも行かない。クライアントがたくさん出入りする状況にはすごく向いてるけど、信頼性はないし、消費者が遅くなるとメッセージが失われることもある。耐久性がないから、消費者が切断されると、その間に送られたメッセージは受け取れない。でも、その分すごく軽量なんだ。トピックはワイルドカードのパスだから、数十億のトピックを持つことができて、RPCも簡単にできる。メッセージを送信して、受信者にランダムに生成されたトピックに返信を投稿させて、そのトピックを聞いて答えを待つって感じ。NATSはブローカーをクラスターに整理して、クラスター間でメッセージを興味に応じてルーティングできるハブ/スポークトポロジーを形成できるから、すごくスケーラブルなんだ。クラスターが消費者の数にスケールしない場合は、最初のクラスターを消費する別のクラスターを追加すれば、ハブ/スポークが二つになる。要するに、NATSは素晴らしい「メッセージルーター」だよ。RPC、キャッシュ無効化チャネル、「アクター」スタイルのプロセス、従来のpub/sub、ログなど、いろんなセマンティクスをその上に構築できる。JetstreamはNATSの上に構築された別の技術で、ストリームを作成できるんだ。ストリームはメッセージの順序付きシーケンスで、耐久性があって、最大保持期間やサイズの設定ができる。ストリームはレプリケートされていて、各ストリームはRaftグループになってる。消費者は特定の位置からフォローすることができる。多くの点でKafkaやRedpandaに似てるけど、「ステロイドを使った」感じで、見た目は似てるけど、ずっとリッチなんだ。例えば、Kafkaはトピックがメッセージのシーケンスで、正確に順番通りに消費されなければならないってことにすごく厳しい。クライアントがイベントのサブセットにサブスクライブしたい場合、クライアント側でフィルタリングするか、フィルタリングしてトピックに書き込む仲介者が必要になる。NATSでは、サーバーにフィルタリングを頼むことができる。Kafkaとは違って、メッセージをnackすることもできるし、サーバーはどの消費者が何を見たかを追跡してくれる。nackすると順序が失われるけど、nackedメッセージは後で戻ってくる。JetstreamもKafkaのような厳密な順序付きモードをサポートしてる。Kafkaとは違って、クライアントはルーティングの挙動を選べるし、ワーカー風のルーティングや決定論的なパーティショニングもできる。Kafkaの厳格なネットワーキングモデル(消費者はパーティションに割り当てられて、トピックを消費するだけ)とは違って、NATSのように複雑なトポロジーを設定できるんだ。例えば、複数のリージョンにストリームを作ってレプリケーションすることで、消費者はローカルリージョンのハブにだけ接続すればいい。NATS/Jetstreamは柔軟性があるけど、パフォーマンスとスケーラビリティの面で妥協してる気がする。Jetstreamクラスターは多くのサーバーにスケールしないし(最大3つを推奨してると思う)、大量の消費者がいるとサーバーがすごく熱くなることがある。nackを消費モデルに取り入れたのは間違いだったとも思う。Kafkaが大きく簡素化しているのは、トピックが厳密にシーケンシャルで、生成と消費の両方でそうだってこと。これによってサーバーがシンプルになり、クライアントは処理できないメッセージに対処しなきゃいけなくなる。Jetstreamでは耐久性のある消費者が厳密に順序付けられることはできないし、SDKが「順序付き消費者」と呼ぶものは一時的な消費者に過ぎない。さらに、一時的な消費者は実際には存在しない。すべての消費者がサーバー側の状態を作成するからね。テストでは、数千の消費者を持つのは本当に悪いアイデアだとわかったよ。(最新のSDKでは、サーバー側の消費者を登録せずに位置からストリームを消費できる「ダイレクトフェッチ」APIが提供されてるけど、まだ試してない。)最後に、サーバーのレプリケーションや接続のメカニズムはかなり謎めいていて、何かがうまくいかないときに理解するのが難しい。さまざまな概念 — リーフノード、リーフクラスター、レプリカ、ミラー、クラスター、ゲートウェイ、アカウント、ドメインなど — があるから、最適なトポロジーを設計するのは簡単じゃない。Kafkaのネットワークモデルは比較的シンプルでストレートフォワードだけど、柔軟性は少ない。Kafkaでは、トピックから読み取って他のトピックに書き込むことで、自分でハブ/スポークトポロジーを構築できるし、これは自分で設定する必要があるけど、魔法のようなものではなく、制御しやすく理解しやすい。私が働いているところでは、NATSを広く使って大成功を収めてる。いくつかのアプリケーションにはJetstreamも採用したけど、上記の理由で少し不満が出てきて、今はKafka互換のRedpandaを使ってる。JSは特定のタイプのアプリにはすごく合ってると思うけど、まずは要件を慎重に評価するべきだね。Jetstreamは「より良いKafka」ってだけじゃないくらい違うから。

愛憎関係の概念を教えるために作られたんだ。

このテーマについてコメントしたいと思ってたんだけど、何度か試した結果、ここにたどり着いた。この記事が自分の気持ちをよく表してるから。記事の主張はすごく説得力がある。でも、Kafkaを選ぶと嫌なことが見えてくるんだよね。多くの理由がバカみたいなことばかりで、クライアントコードの重要じゃないバグが見つかるとか、実験が面倒になるとか、必須の統合テストを書くのに何週間もかかるとか。確かにデータを再生できるけど、受信サービスの特別なケースの問題を全部直さないと再生できないし。多分一番の不満は、パイプの中に何が実際にあるのか理解するのが難しいことかな。s3にしっかりした状態で持っておく方がずっと楽だよね。結局、遅くなるからイライラするんだよね。特に小さなローカライズされたチームだと。

Kafkaの火hoseを取り込んで、いろんなアプリケーションにスロットル可能な形で提供する能力は素晴らしいよ。「ただのデータベースを使えばいい」と思ってるなら、SQLデータベースは書き込みの火hoseを処理するのには向いてないってことを知っておくべきだね。2012年の時点で分散SQLなんてなかったし。KafkaはCAP定理からCを捨てることを完全に受け入れた最初のシステムの一つで、これはスケールのあるウェブアプリケーションにとって大きな前進だったんだ。もしこれに反発を感じるなら、Postgresデータベースのリードレプリカを使うと同じ正確性の問題が出てくるよ。でも最近は、フォーチュン100規模でない限り、Redis Cluster Streamsに絶対に切り替えるかな。管理がずっと簡単で、運用コストも安いし。それに、Kafkaが好きなのは、10年前にサンフランシスコで可愛いロシア人の女の子二人に会ったからなんだ。そのグループで、私たちが働いている会社のことを抽象的に説明して、スタートアップを当てるゲームをしたんだ。彼女たちが「私たちは分散ストリーミングソフトウェアを書く」と言った時、私はすぐに「Confluent」って当てたよ。当時のConfluentはかなり新しくて小さかった。楽しい夜だったな。楽しい時代だった。

Kafkaの火hoseを取り込んで、いろんなアプリケーションにスロットル可能な形で提供する能力は素晴らしいよ。私はまさにそのためにKafkaを使ってる。Redis Cluster StreamsにはAOF永続ログがあるみたいだけど、どれくらい安定してるの?

Redis Cluster Streamsに切り替えた方がいいよ。管理がずっと簡単で、運用コストも安い。Redis Cluster Streamsの管理が簡単だって具体的にどういうことか教えてくれない?個人的には、フォーチュン100規模じゃない場合、Kafkaクラスターのインストールと管理は十分簡単だと思うんだ。Zookeeper用に1つのJavaコマンドを実行して、ブローカー用に別のJavaコマンドを実行すればいいだけだし(最近のKafkaのバージョンではZookeeperはもう必要ない)。設定ファイルはそんなに簡単じゃないけど、複雑でもないし。別のマシンがあれば、別のブローカーを実行できるし。Redis Cluster Streamsが安く運用できるのは、Cで書かれているから?それとも、メッセージがRAMに保存されてSSDじゃないから?

物語が好き! > KafkaはCAP定理からCを落とすことを完全に受け入れた最初のシステムの一つで、これはスケールでのウェブアプリケーションにとって大きな前進だった。これについて詳しく教えてくれない?Cを落とすのはいつのこと?すべてのレプリカが書き込みを確認するのを待たずにKafkaに書き込む場合を指してるの?(acks=1)それがなぜ大きなステップだったのか、他のどのシステムがCを落とすことを受け入れなかったのかも知りたいな。

SQLデータベースは書き込みのファイアホースから飲むのには_あまり向いていない_ これを考えると、みんなが考えすぎてるのかな?単にランデブーハッシュと「eventlog」って名前のヒープテーブルを持つデータベースサーバーを使えば済むのかも…

長い間、Postgres用に物理的に順序付けられた追加専用のテーブルを作れないかと考えていました。KafkaタイプのログにPostgresがあまり向いていない主な理由は、テーブルが順序付けられたデータに対してあまり効率的でないことと、削除がバキュームされるまで膨張を引き起こすことです。新しいテーブルエンジン(テーブルアクセスメソッド)を提供することで両方を解決できるかもしれませんが、物理的に順序付けられたテーブルのためにヒープストレージの配置をどこまで制御できるかは分かりません。でも、削除を早くするためのいろんなトリックもできそうです(追加専用だから更新はなくて、MVCCを使わずに安全に並行読み取りに対してヘッドからプルーニングするだけ?)し、フィルタリングも早くできるでしょう。もちろんKafkaはそれ以上のものですが、これだけでもかなり進むと思います。

LinkedInが最近、KafkaからNorthguardに移行したと発表したよ。NorthguardとXinfraの紹介: LinkedInでのスケーラブルなログストレージ [1] & LinkedIn: ストリーム処理 4.16.25 [2] [1]: https://www.linkedin.com/blog/engineering/infrastructure/int... [2]: https://www.youtube.com/watch?v=RDV6-MUVEbQ

ここ数年Kafkaを追ってなかったけど、LinkedInがかなり投資してたと思ってた。何が起こったの?それとConfluentはどうなったの?彼らのチームはLinkedInのメンバーだったはずだけど。

Northguardってオープンソースになってないみたいですね?Apache Pulsarとの比較が気になります。LIのブログ記事を読むと、いくつかの類似点がある気がします。0: https://pulsar.apache.org/

ちょっと大げさかもしれないけど、Kafka(または多くのシステム間でデータを共有するためのイベント駆動アーキテクチャの概念)は、最も過小評価されている技術の一つだと思う。大企業で使われてるけど、あまり話題にならないよね。

すべてをグラフとしてモデル化するのは、よく罠にハマることがある。モデルがすべてのユースケースを捉えるのに十分柔軟だからといって、それを使うべきだとは限らない。実際には、もっと制約のあるシンプルなモデルの方が好ましい。ビットコインのような分散型台帳は、遷移をイベントとして保存するけど、これはノードが次の状態を検証するために遷移が必要だから。だから、ビットコインはイベント駆動アーキテクチャを使っている広く運用されているソフトウェアだと言えるかも。すべてのシステムが効率的に読み取るためにすべての状態遷移を持つ必要はないし、実際には前の状態と次の状態から遷移を導き出すこともできる(Gitがそうしてる)。Gitはシステムのすべての状態遷移を計算できるけど、イベントを保存するのではなく、スナップショットを保存してるんだよね。

Apache Kafkaは、主にJay Kreps、Neha Narkhede、Jun RaoというLinkedInのエンジニアによって2010年頃に開発されました。その後、2011年にオープンソース化され、2012年にはApache Software Foundationのトップレベルプロジェクトになりました。創設者たちはその後、Kafkaの商業サポートやエンタープライズ機能を提供するConfluentを共同設立しました。

私の意見では、Kafkaの最大の強みはコンシューマグループだと思います。2016年から少なくとも3つのプロジェクトで使ってきましたが、今まで失敗したことはありません。ただ、負荷はそれほど大きくなくて、最大で約100メッセージ/秒くらいです。でも、標準のアプリだけで監視や管理をするのはちょっと難しいですね。

これくらいのデータ量なら、KinesisやPubsubをしっかり検討した方がいいと思います。月に数十ドルくらいのコストで済むはずです。