Apache Pulsarとは?仕組み、Kafkaとの違い、使い方、コード例まで徹底解説
Apache Pulsarは、複数のアプリケーションやサービスの間で発生するデータを、安全かつ効率的に受け渡すための分散メッセージング基盤です。現代のシステムでは、注文処理、決済、在庫更新、通知、ログ収集、分析処理など、多くの処理が同時に動きます。これらをすべて直接つなぐと、ひとつの処理が遅れただけで全体が遅くなり、障害の影響も広がりやすくなります。Apache Pulsarを使うと、送信側は発生したイベントをPulsarへ送り、受信側は自分のタイミングでそのイベントを処理できるため、システム全体をゆるく結合できます。
特にApache Pulsarは、単なるメッセージキューではありません。発行・購読型のメッセージ配信、永続的なデータ保存、柔軟な購読方式、複数組織での利用を想定した管理構造、地理的複製、スキーマ管理、軽量なメッセージ処理、外部システム連携まで含んだ、かなり広い範囲を扱える基盤です。そのため、小さな非同期処理だけでなく、大規模なイベント駆動アーキテクチャ、リアルタイム分析基盤、マイクロサービス間通信、ログ基盤、IoTデータ収集などにも利用できます。
この記事では、Apache Pulsarとは何かを、初心者にも分かるように日本語で整理しながら、実際の開発・運用で重要になる考え方まで詳しく解説します。見出しごとに役割、仕組み、設計ポイント、注意点を分けて説明し、JavaやPythonのコード例も入れています。単に用語を覚えるのではなく、なぜPulsarが必要なのか、どのような場面で強みを発揮するのか、導入するときに何を設計すべきなのかまで理解できる内容にしています。
1. Apache Pulsarとは
Apache Pulsarとは、アプリケーション同士がメッセージを送受信するための、オープンソースの分散メッセージング基盤です。送信側のサービスは、発生したデータやイベントをPulsarのトピックへ送信し、受信側のサービスはそのトピックを購読してメッセージを受け取ります。これにより、送信側と受信側が直接依存しなくなり、片方の処理が遅れても、もう片方を止めずに済む構成を作れます。
Pulsarの大きな特徴は、メッセージ配信を担当する部分と、メッセージ保存を担当する部分が分かれていることです。多くのメッセージ基盤では、受信・配信・保存が同じ役割のサーバーにまとまりがちですが、Pulsarではブローカーが通信と配信を担当し、Apache BookKeeperが保存を担当します。この設計によって、配信負荷が高い場合と保存容量が足りない場合を分けて考えられ、大規模環境での拡張性を高めやすくなります。
1.1 Apache Pulsarの役割
Apache Pulsarの役割は、システム内で発生するイベントやメッセージを、必要なサービスへ安全に届けることです。たとえばECサイトで注文が作成されたとき、注文サービスが決済サービス、在庫サービス、配送サービス、通知サービスを順番に直接呼び出す設計にすると、どこかのサービスが遅いだけで注文処理全体が遅くなります。Pulsarを使えば、注文サービスは「注文が作成された」というイベントを送るだけで済み、他のサービスはそのイベントを自分の購読で受け取って処理できます。
このような構成にすると、各サービスは独立して開発、停止、再起動、拡張しやすくなります。決済サービスが一時的に停止しても、イベント自体はPulsarに保持されるため、復旧後に処理を再開できます。また、新しく分析サービスを追加したい場合も、既存の注文サービスを大きく変更せずに、同じイベントを購読するだけでデータを利用できます。つまりPulsarは、システムを柔軟に成長させるための中継基盤として働きます。
1.2 メッセージング基盤としての意味
メッセージング基盤とは、アプリケーション間でデータを直接渡すのではなく、専用の中継システムを通して渡す仕組みです。送信者はメッセージを基盤へ送り、受信者はその基盤からメッセージを受け取ります。この仕組みを使うことで、送信者は受信者の数、状態、処理速度を細かく意識しなくてよくなります。これは、サービス数が増えるほど重要になります。
Apache Pulsarは、単純な仕事の分配だけでなく、複数の受信者に同じイベントを配る用途にも向いています。たとえば、ひとつのユーザー行動イベントを、リアルタイム分析、推薦システム、不正検知、ログ保存のすべてに使いたい場合があります。Pulsarでは、同じトピックに対して複数の購読を作れるため、それぞれの処理が独立した読み取り位置を持ってイベントを処理できます。これにより、同じデータを複数の目的で再利用しやすくなります。
1.3 イベント駆動との関係
イベント駆動とは、システム内で何かが起きたことをイベントとして記録し、そのイベントをきっかけに別の処理を動かす設計方法です。たとえば「注文が作成された」「支払いが完了した」「ユーザーがログインした」「商品が発送された」といった出来事をイベントとして扱います。Apache Pulsarは、これらのイベントを安全に運び、必要なサービスへ配信する役割を担います。
イベント駆動にすると、ひとつの大きな処理を複数の小さな処理へ分けやすくなります。注文サービスは注文イベントを出すだけで、通知サービスは通知だけ、分析サービスは分析だけ、在庫サービスは在庫更新だけに集中できます。結果として、各サービスの責任範囲が明確になり、変更の影響範囲も小さくなります。Pulsarは、このようなイベント駆動型の設計を実現するための中核的な部品になります。
1.4 永続保存を前提にした仕組み
Apache Pulsarでは、永続トピックに送られたメッセージをディスクへ保存できます。これは、受信側が一時的に停止していても、メッセージを失わずに後で処理できるという意味です。業務システムでは、注文、決済、監査ログ、在庫変更など、失うと大きな問題になるデータが多いため、メッセージを単に一時的に流すだけでは不十分です。Pulsarの永続保存は、そのような重要データを扱うために必要な性質です。
また、永続保存があることで、再処理や遅延処理も行いやすくなります。たとえば分析基盤に障害が起き、数時間分のイベント処理が止まったとしても、イベントが保持されていれば復旧後に追いつくことができます。さらに、システムの不具合によって一部の処理をやり直したい場合にも、過去のメッセージを再度読む設計を検討できます。このように、Pulsarはリアルタイム配信だけでなく、信頼性の高いデータ処理にも向いています。
1.5 大規模システムで使われる理由
Apache Pulsarが大規模システムで注目される理由は、単に速くメッセージを送れるからではありません。複数のチーム、複数のサービス、複数のデータ種別、複数の地域をひとつの基盤で扱いやすい設計になっている点が大きな理由です。テナント、名前空間、トピックという階層で管理できるため、組織や用途ごとに設定や権限を分けることができます。
大規模な企業では、ひとつの部署だけでなく、多くのチームが同時にメッセージ基盤を使います。そのとき、すべてのチームが自由にトピックを作り、自由にデータを流すと、管理不能になります。Pulsarでは、名前空間ごとに保持期間、権限、スキーマ、複製設定などを管理できるため、共通基盤として運用しやすくなります。これは、小規模なキューではなく、企業全体のイベント基盤として使う場合に大きな価値を持ちます。
2. Apache Pulsarの仕組み
Apache Pulsarの仕組みは、送信者、受信者、トピック、購読、ブローカー、保存層の関係で理解できます。送信者はトピックへメッセージを送り、受信者は購読を通じてそのメッセージを読み取ります。ブローカーは、送信者と受信者の接続を受け付け、メッセージの流れを制御します。そして、永続的に保存する必要があるメッセージはBookKeeperへ保存されます。
この構造を理解すると、Pulsarがなぜ拡張しやすいのかが見えてきます。送信・受信の通信処理と、ディスクへの保存処理が分離されているため、負荷の種類に応じて別々に拡張できます。接続数や配信量が増えた場合はブローカーを増やし、保存容量や書き込み量が増えた場合はBookKeeper側を増やすという考え方ができます。
2.1 送信者の動き
送信者は、アプリケーション内で発生したイベントやデータをPulsarへ送る役割を持ちます。注文サービスであれば注文作成イベント、ユーザー管理サービスであれば登録イベントやログインイベント、決済サービスであれば支払い完了イベントを送信します。送信者は、どのトピックへ送るか、どの形式で送るか、失敗時に再試行するかなどを設定します。
送信者にとって重要なのは、受信側の処理を直接待たなくてよいことです。通常の同期呼び出しでは、相手のサービスが応答するまで待つ必要がありますが、Pulsarへメッセージを送る方式では、メッセージを基盤へ渡した時点で送信側の処理を進めやすくなります。これにより、ユーザーに返す応答時間を短くしたり、ピーク時の負荷を平準化したりできます。
2.2 受信者の動き
受信者は、Pulsarのトピックを購読し、届いたメッセージを処理します。受信者は購読名を持つため、同じトピックを読んでいても、処理目的ごとに独立した読み取り位置を持てます。たとえば、通知サービスと分析サービスが同じ注文イベントを読んでいても、それぞれ別の購読名を使えば、互いの処理速度に影響されにくくなります。
受信者は、メッセージを正しく処理した後に確認応答を返します。この確認応答によって、Pulsarはそのメッセージが処理済みであると判断します。もし受信者が処理中に落ちたり、エラーを出したりした場合、確認応答されていないメッセージは再配信の対象になります。これにより、処理失敗時にもメッセージを失いにくくなります。
2.3 トピックの役割
トピックは、メッセージを分類して流すための名前付きの通り道です。注文イベント、決済イベント、ユーザー行動イベント、エラーログなど、データの種類や用途ごとにトピックを分けます。トピックを適切に設計すると、どのデータがどこを流れているのかが分かりやすくなり、受信側も必要なデータだけを購読できます。
トピック設計が悪いと、後から運用が難しくなります。たとえば、すべてのイベントをひとつの大きなトピックに入れてしまうと、受信側で不要なデータを大量に読み捨てる必要が出ます。逆に、細かく分けすぎると、トピック数が増えすぎて管理が煩雑になります。Pulsarでは、業務イベントの意味単位でトピックを作り、名前空間で整理する設計が重要です。
2.4 購読の意味
購読は、受信者がトピックをどのように読むかを管理する仕組みです。同じトピックでも、購読名が異なれば読み取り位置は別々に管理されます。これは、同じイベントを複数の用途で使うときに非常に便利です。分析用の購読が遅れても、通知用の購読は通常通り進められます。
購読は、単にメッセージを読む入口ではなく、処理状態を管理する重要な単位です。どこまで読んだか、未確認メッセージがどれだけあるか、どれだけ遅延しているかは、購読ごとに確認します。そのため、購読名は適当に付けるのではなく、どのサービスのどの処理なのかが分かる名前にするべきです。
2.5 保存層との連携
Apache Pulsarでは、ブローカーがメッセージを受け取った後、永続トピックのデータはBookKeeperへ保存されます。BookKeeperは分散された保存ノード群として動作し、メッセージを複数の場所に書き込むことで耐障害性を高めます。これにより、ひとつの保存ノードに問題が起きても、データを失いにくい構成を作れます。
保存層が独立していることは、Pulsarの設計上とても重要です。ブローカーは比較的軽い状態で動けるため、障害時に担当トピックを別ブローカーへ移しやすくなります。また、保存容量の拡張と配信性能の拡張を分けて考えられるため、負荷の性質に応じた運用ができます。大規模な本番環境では、この分離設計が運用上の大きな利点になります。
3. Apache Pulsarの主要構成要素
Apache Pulsarは、ひとつの単純なサーバーだけで動く仕組みではなく、複数の構成要素が役割分担して動きます。主な構成要素には、ブローカー、BookKeeper、メタデータストア、プロキシ、クライアントがあります。それぞれの役割を理解することで、Pulsarの障害対応、性能設計、拡張方法を考えやすくなります。
特に本番運用では、「メッセージが送れない」「受信が遅い」「保存容量が増えている」「購読が詰まっている」といった問題が起きたとき、どの構成要素を確認すべきか判断する必要があります。Pulsarの構成を理解していないと、障害の原因を見つけるのに時間がかかります。そのため、開発者だけでなく運用担当者も、各要素の役割を把握しておくべきです。
3.1 ブローカー
ブローカーは、送信者と受信者が接続するPulsarの入口です。送信者からメッセージを受け取り、受信者へメッセージを配信し、トピックの担当管理や通信制御を行います。クライアントから見ると、Pulsarに接続するときの相手は基本的にブローカーまたはプロキシになります。
ブローカーは、メッセージ本体を長期保存する役割を中心には持ちません。永続データの保存はBookKeeperに任せるため、ブローカーは接続、配信、ルーティングに集中できます。このため、ブローカーが停止しても、保存済みのメッセージがすぐに消えるわけではありません。別のブローカーが処理を引き継げる設計になっているため、高可用性を実現しやすくなります。
3.2 Apache BookKeeper
Apache BookKeeperは、Pulsarのメッセージを永続的に保存するための分散保存システムです。Pulsarでは、重要なメッセージをディスクへ保存し、受信者が処理するまで保持する必要があります。その保存処理を担うのがBookKeeperです。BookKeeperは、追記型のログ構造を使い、複数の保存ノードへデータを分散して保持します。
BookKeeperがあることで、Pulsarは高い耐久性を持てます。たとえば、ある受信者が長時間停止していても、メッセージが保存されていれば後から処理できます。また、複数の保存ノードへ複製しておけば、単一ノード障害によるデータ損失リスクを下げられます。ただし、BookKeeperはPulsarの信頼性を支える重要部品なので、ディスク使用量、書き込み遅延、ノード状態をしっかり監視する必要があります。
3.3 メタデータストア
メタデータストアは、Pulsarクラスタの状態や設定情報を管理する役割を持ちます。トピックがどのブローカーに担当されているか、名前空間の設定はどうなっているか、スキーマ情報は何か、クラスタ内の構成情報はどうなっているかといった情報を保持します。Pulsar全体が協調して動くためには、このメタデータ管理が欠かせません。
メタデータストアに問題が起きると、新しいトピック操作、設定変更、クラスタ管理に影響が出る可能性があります。そのため、本番環境ではメタデータストアも単一障害点にしない構成が重要です。Pulsarをただ動かすだけなら意識しにくい部分ですが、実際の運用では、メタデータストアの安定性がクラスタ全体の安定性に関わります。
3.4 プロキシ
プロキシは、クライアントからPulsarクラスタへの接続を中継する役割を持ちます。ブローカーが複数台ある環境では、クライアントが各ブローカーへ直接接続するよりも、プロキシやロードバランサを通した方がネットワーク構成を整理しやすくなります。特に、外部ネットワークからPulsarへ接続させる場合、プロキシを使うことでセキュリティ境界を作りやすくなります。
プロキシは、認証、接続制御、ネットワーク分離の観点でも役立ちます。たとえば、内部のブローカーを直接公開したくない場合、外部にはプロキシだけを公開し、内部ネットワークでブローカーへ接続させる構成にできます。ただし、プロキシも通信経路上の重要な部品になるため、単体構成ではなく冗長化し、負荷分散や監視を行うことが必要です。
3.5 クライアント
クライアントは、アプリケーションからPulsarへ接続するためのライブラリです。Java、Python、Goなど、複数の言語向けにクライアントが用意されています。開発者はクライアントを使って送信者や受信者を作成し、トピック名、購読名、認証情報、スキーマなどを指定してメッセージを送受信します。
クライアント設計では、接続失敗、送信失敗、再試行、タイムアウト、確認応答、重複処理への対策が重要です。サンプルコードでは数行で送受信できますが、本番ではネットワーク障害やPulsar側の一時的な負荷上昇を考慮する必要があります。クライアント側で適切なログ出力、例外処理、再試行制御を入れることで、障害時にも原因を追いやすくなります。
4. Apache Pulsarのトピック
Apache Pulsarにおけるトピックは、メッセージを分類して流すための中心的な単位です。送信者は特定のトピックへメッセージを送り、受信者はそのトピックを購読してメッセージを受け取ります。トピックをどう設計するかによって、システム全体の分かりやすさ、処理効率、運用性が大きく変わります。
トピック設計では、永続トピックにするか、非永続トピックにするか、分割するか、名前空間をどう分けるか、保持期間をどう設定するかを考えます。最初に適当に作ってしまうと、後から受信者が増えたり、データ量が増えたりしたときに整理しにくくなります。Pulsarを導入する場合、コードを書く前にトピック設計を行うことが重要です。
4.1 永続トピック
永続トピックは、メッセージをディスクへ保存するトピックです。受信者が停止していても、メッセージを保存しておき、後から処理できるようにします。注文、決済、在庫、監査ログ、ユーザー行動履歴など、失ってはいけないデータを扱う場合は、基本的に永続トピックを使うべきです。
永続トピックは信頼性が高い一方で、保存容量や書き込み性能を意識する必要があります。すべてのデータを長期間保存すると、ストレージコストが増え続けます。そのため、トピックごと、名前空間ごとに保持期間や保存容量の上限を設計する必要があります。重要データは長く保持し、一時的なログや再利用しないデータは短めにするなど、用途に応じた設定が大切です。
4.2 非永続トピック
非永続トピックは、メッセージをディスクへ保存せず、主に一時的な配信に使うトピックです。速度や低遅延を重視し、メッセージ損失が許容できる場合に利用できます。たとえば、リアルタイムの一時通知、短時間だけ意味を持つ状態情報、失われても再生成できるデータなどが候補になります。
ただし、非永続トピックは重要な業務データには向きません。ブローカー障害や接続切断が起きた場合、メッセージが失われる可能性があるためです。非永続トピックを使う場合は、「このデータは失われても問題ないか」「後から再送できるか」「利用者が損失を理解しているか」を確認する必要があります。速度だけを理由に重要データを非永続にするのは危険です。
4.3 分割トピック
分割トピックは、ひとつの論理的なトピックを複数の分割に分けて扱う仕組みです。大量のメッセージを高い並列度で処理したい場合、ひとつのトピックだけでは処理能力が足りないことがあります。そのような場合、分割を使うことで、複数のブローカーや受信者に負荷を分散できます。
分割数を増やすと性能面では有利になりますが、設計は複雑になります。特に順序性が重要なイベントでは、どのキーで分割されるかを意識する必要があります。たとえば、同じ注文IDのイベントが別々の分割へ送られると、受信順序の管理が難しくなる場合があります。そのため、分割トピックを使うときは、処理量、順序要件、キー設計をまとめて考えることが重要です。
4.4 トピック命名
トピック名は、運用しやすさに直結する重要な設計項目です。名前を見ただけで、どの業務領域の、どの環境の、どの種類のイベントなのかが分かるようにするべきです。たとえば、注文作成イベントなら order-created、決済完了イベントなら payment-completed のように、イベントの意味を明確に表す名前が望ましいです。
悪い命名は、時間が経つほど問題になります。test-topic、data-topic、event1 のような名前は、最初は便利でも、後から誰も意味を判断できなくなります。さらに、本番環境と検証環境の区別が曖昧だと、誤って本番データを検証処理へ流す危険もあります。トピック命名規則は、Pulsar導入初期にチームで決め、ドキュメント化しておくべきです。
4.5 トピック設計の注意点
トピックを大きくまとめすぎると、受信者が不要なメッセージまで受け取り、自分でフィルタしなければならなくなります。これは処理効率を下げるだけでなく、受信側のコードを複雑にします。逆に、トピックを細かく分けすぎると、管理対象が増えすぎ、保持期間、権限、スキーマ、監視設定の管理が大変になります。
適切なトピック設計では、業務上の意味、受信者の用途、データ量、順序性、保持期間を総合的に考えます。たとえば、注文作成、注文キャンセル、注文更新を同じ注文イベントとして扱うべきか、それぞれ別トピックにするべきかは、受信側がどう処理するかによって変わります。Pulsarでは柔軟に設計できますが、その自由度を活かすには、最初に設計方針を明確にする必要があります。
5. Apache Pulsarの購読方式
Apache Pulsarの購読方式は、同じトピックのメッセージを受信者がどのように受け取るかを決める仕組みです。購読方式を正しく選ぶことで、順序を重視する処理、並列処理を重視する処理、障害時の切り替えを重視する処理を、それぞれ適切に設計できます。
購読方式を理解せずに使うと、想定外の順序崩れ、重複処理、処理遅延が発生しやすくなります。たとえば、順序が重要な処理で共有購読を使うと、複数の受信者にメッセージが分散され、順番通りに処理されない可能性があります。Pulsarを使うときは、購読方式を単なる設定項目ではなく、処理設計の一部として考える必要があります。
5.1 排他購読
排他購読は、ひとつの購読に対して、基本的にひとつの受信者だけがメッセージを受け取る方式です。ひとつの処理が順番にメッセージを処理するため、比較的シンプルに動作を理解できます。順序性を重視する処理や、同時に複数の受信者が処理すると問題が起きる処理に向いています。
一方で、排他購読は処理能力を水平に伸ばしにくいという弱点があります。受信者がひとつだけなので、その受信者の処理速度が全体の上限になります。メッセージ量が増えて処理が追いつかなくなった場合、受信者の性能を上げるか、トピック分割や別の購読方式を検討する必要があります。単純で安全ですが、大量処理には慎重な設計が必要です。
5.2 共有購読
共有購読は、同じ購読名に複数の受信者が参加し、メッセージを分担して処理する方式です。ワーカーを増やすことで処理能力を高めやすく、大量の独立したタスクを並列処理したい場合に向いています。たとえば、画像処理、通知送信、ログ変換、外部API連携など、メッセージごとの処理が独立している場合に使いやすいです。
ただし、共有購読ではメッセージの厳密な順序を保ちにくくなります。複数の受信者が同時に処理するため、先に送られたメッセージより後に送られたメッセージの方が先に処理完了することがあります。そのため、注文状態の遷移や口座残高の更新など、順序が重要な処理には注意が必要です。共有購読を使う場合は、各メッセージが独立して処理できるかを確認するべきです。
5.3 フェイルオーバー購読
フェイルオーバー購読は、複数の受信者を用意しながら、通常はひとつの受信者が主担当としてメッセージを処理する方式です。主担当の受信者に障害が起きた場合、別の受信者へ処理が切り替わります。これにより、処理の継続性を高めながら、共有購読よりも順序を保ちやすい構成を作れます。
この方式は、処理能力の拡張よりも可用性を重視する場面に向いています。常に複数の受信者で並列処理するわけではないため、大量処理の性能向上には限界があります。しかし、重要な業務処理を止めたくない場合や、主処理者が落ちたときに自動的に待機系へ切り替えたい場合には有効です。障害時の継続性を設計するうえで便利な購読方式です。
5.4 キー共有購読
キー共有購読は、同じキーを持つメッセージを同じ受信者へ届けやすくする方式です。ユーザーID、注文ID、商品ID、口座IDなど、同じ対象に関するイベントを同じ受信者で処理したい場合に使います。これにより、キー単位の順序性を意識しながら、全体としては複数の受信者で並列処理できます。
キー共有購読は、順序性と並列性のバランスを取りたい場面で便利です。ただし、キーの偏りには注意が必要です。特定のユーザーや注文にメッセージが集中すると、そのキーを担当する受信者だけが高負荷になります。キー設計が悪いと、せっかく複数の受信者を用意しても負荷が均等に分散されません。キー共有を使う場合は、キーの分布も運用上の監視対象になります。
5.5 購読名の設計
購読名は、どの処理がどこまでメッセージを読んだかを管理するための名前です。適当に付けると、後から購読の目的が分からなくなり、不要な購読を消してよいのか判断できなくなります。購読名には、サービス名、処理目的、環境名などを含めると分かりやすくなります。
購読は、読み取り位置や未確認メッセージの状態を持つため、作りっぱなしにすると保存量の増加につながることがあります。使われなくなった購読が残っていると、Pulsarはその購読のためにメッセージを保持し続ける場合があります。したがって、購読名の命名規則だけでなく、不要な購読を定期的に確認・削除する運用も必要です。
6. Apache PulsarとKafkaの違い
Apache PulsarとApache Kafkaは、どちらも分散メッセージングやイベントストリーミングで使われる代表的な技術です。ただし、内部構造、保存方式、購読モデル、マルチテナント性、運用の考え方には違いがあります。どちらが常に優れているという話ではなく、システムの要件、組織の経験、運用体制によって選び方が変わります。
Pulsarは、ブローカーと保存層を分離した設計、柔軟な購読方式、テナントと名前空間による管理、地理的複製のしやすさが特徴です。一方、Kafkaは長年の実績があり、周辺ツールやエコシステムが非常に豊富です。すでにKafkaを運用している組織では、その知識と資産を活かせる点が大きなメリットになります。
6.1 アーキテクチャの違い
Pulsarは、メッセージの配信を担当するブローカーと、保存を担当するBookKeeperが分かれています。ブローカーはクライアント接続、メッセージ配信、トピック担当管理に集中し、データの永続保存はBookKeeperが担います。この分離によって、配信負荷と保存負荷を別々に拡張しやすくなります。
Kafkaは一般的に、ブローカーがメッセージの受信、配信、保存をまとめて担当します。この構造は理解しやすく、運用対象も比較的まとまりやすい反面、保存負荷と配信負荷が同じブローカーに集まりやすくなります。Pulsarは構成要素が多い分、設計は複雑になりますが、大規模環境では役割分離による柔軟性が強みになります。
| 比較項目 | Apache Pulsar | Apache Kafka |
|---|---|---|
| 基本構造 | ブローカーと保存層を分離 | ブローカーが保存も担当 |
| 保存基盤 | Apache BookKeeper | Kafkaブローカーのログ |
| 購読方式 | 排他、共有、フェイルオーバー、キー共有を選択可能 | 消費者グループを中心に設計 |
| 管理階層 | テナント、名前空間、トピックで整理しやすい | トピック中心で運用設計することが多い |
| 大規模共有 | 複数チーム利用を想定しやすい | 運用設計で対応することが多い |
| 地理的複製 | 標準的に考えやすい | 追加機能や周辺ツールを使うことが多い |
| 学習コスト | 構成要素が多く高め | 普及情報が多く学びやすい |
| 向く場面 | マルチテナント、大規模共有、柔軟な購読 | 広い採用実績、豊富な周辺連携 |
6.2 保存方式の違い
Pulsarでは、BookKeeperがメッセージ保存を担当します。BookKeeperは分散された保存層として動作し、メッセージを複数ノードに保存することで耐久性を高めます。この仕組みにより、ブローカーが停止しても保存済みデータを失いにくく、別のブローカーが担当を引き継ぎやすくなります。
Kafkaでは、各ブローカーが自分の担当する分割ログを保存します。これはシンプルで強力な設計ですが、ブローカーのディスク容量、入出力性能、ネットワーク負荷を慎重に設計する必要があります。Pulsarは保存層を切り離しているため、保存容量を増やしたいときと、配信能力を増やしたいときを分けて対応しやすいという違いがあります。
6.3 購読モデルの違い
Pulsarは、排他、共有、フェイルオーバー、キー共有という複数の購読方式を提供します。これにより、順序重視、並列処理重視、障害切り替え重視、キー単位の順序重視など、用途に応じて読み方を選べます。同じトピックに対して複数の購読を作り、それぞれ独立した処理として動かせる点も分かりやすい特徴です。
Kafkaは、消費者グループと分割を中心に設計します。ひとつの消費者グループ内では、分割ごとに消費者が割り当てられ、同じグループ内で負荷分散が行われます。この仕組みは非常に強力ですが、Pulsarのように購読方式を明示的に選ぶ設計とは考え方が異なります。どちらが分かりやすいかは、チームの経験や用途によって変わります。
6.4 運用面の違い
Pulsarは、ブローカー、BookKeeper、メタデータストアなど複数の構成要素を運用する必要があります。そのため、初期学習や監視設計には手間がかかります。しかし、役割が分かれているため、問題が起きたときに「配信の問題なのか」「保存の問題なのか」「メタデータ管理の問題なのか」を分けて考えやすい面もあります。
Kafkaは、採用事例が多く、運用ノウハウや周辺ツールが豊富です。監視、スキーマ管理、コネクタ、ストリーム処理などのエコシステムも成熟しています。一方で、大規模な再配置、保存容量管理、分割設計、消費者遅延の管理など、Kafkaにも難しい運用課題はあります。選定時には、技術の機能だけでなく、自社チームがどちらを安定運用できるかを見る必要があります。
6.5 選び方の目安
Apache Pulsarは、複数チームが共通基盤を共有する場合、購読方式を柔軟に選びたい場合、保存と配信を分けて拡張したい場合、地理的複製を重視する場合に向いています。特に、マイクロサービスが多く、同じイベントを複数用途で使う環境では、Pulsarの管理構造と購読方式が役立ちます。
Apache Kafkaは、既にKafkaを使っている組織、Kafkaの周辺ツールを活用したい組織、広く使われている技術を選びたい組織に向いています。Kafkaの経験者が多いチームでは、導入後の教育コストも下がります。最終的には、性能比較だけでなく、運用体制、既存システム、開発者の慣れ、障害対応能力まで含めて判断するのが現実的です。
7. Apache Pulsarのメリット
Apache Pulsarのメリットは、単にメッセージを送受信できることではありません。保存と配信の分離、柔軟な購読方式、マルチテナント管理、地理的複製、スキーマ管理、外部連携など、大規模システムで必要になる機能がまとまっている点に価値があります。特に、複数サービスが同じイベントを別々の目的で使う環境では、Pulsarの設計が大きな力を発揮します。
また、Pulsarは将来的な拡張を考えやすい基盤です。最初は小さな非同期処理から始めても、後から分析基盤、通知基盤、監査ログ、機械学習用データ連携へ広げることができます。ひとつのメッセージ基盤を中心に、システム全体のデータ流通を整備できる点が大きなメリットです。
7.1 水平拡張しやすい
Pulsarは、配信を担当するブローカーと、保存を担当するBookKeeperを別々に拡張できます。たとえば、クライアント接続数や配信量が増えている場合はブローカーを増やし、保存容量や書き込み負荷が増えている場合はBookKeeperを増やすという考え方ができます。これは、負荷の種類が変わりやすい大規模システムでは重要です。
水平拡張しやすいということは、将来の成長に対応しやすいという意味でもあります。最初は少ないノードで始め、サービス数やメッセージ量が増えたら段階的にクラスタを広げられます。ただし、拡張できるからといって設計なしに使うのは危険です。分割トピック、購読方式、保持期間、保存容量を合わせて設計することで、Pulsarの拡張性を正しく活かせます。
7.2 マルチテナントに強い
Pulsarは、テナントと名前空間を使って利用領域を分けられます。たとえば、決済チーム、分析チーム、通知チームが同じPulsarクラスタを使っていても、それぞれのテナントや名前空間を分けることで、設定や権限を管理しやすくなります。これは、企業内で共通メッセージ基盤を作る場合に非常に便利です。
マルチテナントに強いということは、単に名前を分けられるというだけではありません。名前空間ごとに保持期間、複製設定、権限、スキーマ互換性などを管理できるため、用途ごとに違うルールを適用できます。重要な決済イベントは長く保存し、分析用の一時イベントは短く保存する、といった運用がしやすくなります。
7.3 購読方式が柔軟
Pulsarでは、排他、共有、フェイルオーバー、キー共有といった購読方式を選べます。これにより、処理の目的に合わせて読み方を変えられます。順序を守りたい処理は排他やキー共有、処理能力を高めたい処理は共有、障害時に待機系へ切り替えたい処理はフェイルオーバーというように使い分けられます。
この柔軟性は、同じイベントを複数のサービスが異なる方法で処理する場合に特に有効です。たとえば、注文イベントを通知サービスは共有購読で高速処理し、監査サービスは排他購読で順序重視に処理し、分析サービスは別の購読で大量処理することができます。同じデータを用途ごとに最適な読み方で使える点が、Pulsarの大きな魅力です。
7.4 地理的複製に対応しやすい
Pulsarは、複数地域のクラスタ間でメッセージを複製する設計を考えやすい基盤です。グローバルサービスでは、東京、シンガポール、アメリカ、ヨーロッパなど複数地域にシステムを配置することがあります。その場合、ある地域で発生したイベントを別の地域でも利用したい場面があります。
地理的複製を使うと、災害対策、地域分散、低遅延配信、データのバックアップに役立ちます。ただし、複数地域にデータを複製する場合は、ネットワーク遅延、データ主権、法規制、重複処理、障害時の切り替えを考える必要があります。Pulsarはこのような構成を取りやすいですが、設計なしに有効化すればよいわけではありません。
7.5 スキーマ管理が使える
Pulsarは、メッセージの構造を管理するスキーマ機能を持っています。これにより、送信側と受信側が同じデータ形式を理解しているかを確認しやすくなります。特に複数チームが同じトピックを使う場合、データ形式が勝手に変わると下流システムが壊れる可能性があります。スキーマ管理は、そのような事故を防ぐために重要です。
スキーマ管理を使うと、項目追加、型変更、互換性の確認などをルール化できます。たとえば、新しい項目を追加する場合は後方互換を守る、既存項目を削除する場合は段階的に移行する、といった運用ができます。Pulsarのスキーマ機能は、短期的な開発速度だけでなく、長期運用におけるデータ品質維持にも役立ちます。
8. Apache Pulsarのデメリット
Apache Pulsarには多くのメリットがありますが、すべてのシステムに最適というわけではありません。構成要素が多く、学習コストや運用コストが高くなる場合があります。特に、単純なキュー処理だけをしたい小規模システムでは、Pulsarは機能が多すぎて扱いにくいと感じる可能性があります。
導入前には、Pulsarの強みが自社の課題に合っているかを確認する必要があります。大規模なイベント基盤、複数チーム共有、永続保存、柔軟な購読方式が必要ならPulsarは有力です。しかし、数個のジョブを非同期で実行するだけなら、より軽量な仕組みの方が運用しやすい場合もあります。
8.1 学習コストが高い
Pulsarを理解するには、トピック、購読、ブローカー、BookKeeper、メタデータストア、テナント、名前空間、スキーマ、Functions、IOなど、多くの概念を学ぶ必要があります。単純にメッセージを送って受け取るだけなら簡単に始められますが、本番で正しく運用するには内部構造を理解する必要があります。
学習コストが高いと、チーム内で知識が偏りやすくなります。特定の担当者だけがPulsarを理解している状態では、その人が不在のときに障害対応が難しくなります。そのため、導入時には設計書、運用手順、トラブルシューティング手順を整備し、チーム全体で知識を共有することが重要です。
8.2 構成要素が多い
Pulsarは、ブローカー、BookKeeper、メタデータストアなど、複数の部品が連携して動きます。これは大規模運用では強みになりますが、小規模運用では複雑さになります。単体モードで試すだけなら簡単ですが、本番では各部品の冗長化、監視、バックアップ、バージョン管理を考えなければなりません。
構成要素が多いということは、障害原因の候補も増えるということです。メッセージが遅れている場合、それが送信者の問題なのか、受信者の問題なのか、ブローカーの問題なのか、BookKeeperの書き込み遅延なのか、メタデータストアの問題なのかを切り分ける必要があります。Pulsarを導入するなら、監視とログ設計を最初から用意するべきです。
8.3 運用監視が重要
Pulsarでは、ブローカーの負荷、BookKeeperのディスク使用量、書き込み遅延、購読遅延、未確認メッセージ数、トピック数、接続数など、多くの指標を監視する必要があります。これらを見ていないと、障害の前兆や処理遅延に気づくのが遅れます。特に購読遅延は、受信側処理が追いついているかを見る重要な指標です。
監視が不十分な状態でPulsarを本番導入すると、「Pulsar自体は動いているが、実は受信処理が何時間も遅れている」という状態が起こり得ます。メッセージ基盤はシステム全体の中継点になるため、問題が発生すると影響範囲が広くなります。導入前に、何を正常とし、どの値を超えたらアラートにするかを決めておく必要があります。
8.4 小規模用途では過剰な場合がある
Pulsarは高機能な基盤ですが、その分、管理すべきことも多くなります。小さなアプリケーションで、単に数件の非同期ジョブを処理したいだけなら、クラウドの簡易キューや軽量なメッセージブローカーで十分な場合があります。Pulsarを導入すると、基盤そのものの運用が負担になることがあります。
技術選定では、「将来使うかもしれない機能」だけでなく、「今本当に必要な機能」を見るべきです。将来的に複数サービスでイベントを共有し、永続保存や再処理、複数購読、スキーマ管理が必要になるならPulsarは検討に値します。しかし、現時点で単純な非同期化だけが目的なら、より簡単な選択肢を選んだ方が開発速度は上がる可能性があります。
8.5 既存システムとの接続設計が必要
Pulsarを導入しても、既存のデータベース、分析基盤、ログ基盤、業務システムとうまく接続できなければ価値は限定的です。イベントをどこから取り込み、どこへ流し、どの形式で保存し、誰が利用するのかを設計する必要があります。ただPulsarを立てただけでは、データ基盤として機能しません。
既存システムとの連携では、Pulsar IOや専用アプリケーションを使えますが、どちらを選ぶかも重要です。単純な取り込みや書き出しならコネクタで十分な場合がありますが、複雑な変換や業務ロジックがある場合は専用サービスの方が保守しやすいこともあります。Pulsarを中心に据えるなら、周辺システムとの責務分担を明確にする必要があります。
9. Apache Pulsarの使い方
Apache Pulsarの基本的な使い方は、クラスタを起動し、トピックを決め、送信者と受信者を実装する流れです。最初は単体モードで試し、トピックへメッセージを送り、購読を通じて受信する感覚を掴むのが分かりやすいです。その後、本番に近い構成で、認証、権限、監視、保持期間、スキーマ管理を追加していきます。
サンプルコードでは簡単に見えますが、本番では失敗時の動作が非常に重要です。送信に失敗した場合の再試行、受信処理中にエラーが起きた場合の再配信、同じメッセージが複数回届いた場合の重複対策などを設計する必要があります。Pulsarの使い方は、コードの書き方だけでなく、失敗を前提にした処理設計まで含めて考えるべきです。
9.1 ローカルで試す
Pulsarを学ぶ最初のステップとして、ローカル環境で単体モードを起動する方法があります。単体モードでは、学習に必要な構成要素がひとつの環境で動くため、トピック作成、送信、受信、管理コマンドを手軽に確認できます。複雑な分散構成をいきなり作るより、まずは小さく動かして概念を理解する方が効率的です。
ただし、単体モードは本番構成ではありません。耐障害性、性能、保存層の冗長化、メタデータ管理など、本番に必要な要素は別途設計する必要があります。単体モードはあくまで学習や開発検証のための入口と考え、本番導入時には複数ノード構成、監視、バックアップ、セキュリティを検討するべきです。
Dockerで単体起動するコード例
docker run -it \
-p 6650:6650 \
-p 8080:8080 \
apachepulsar/pulsar:latest \
bin/pulsar standalone
このコマンドを実行すると、ローカル環境でPulsarを試せる状態になります。6650 はPulsarクライアントが接続するためのポートで、8080 は管理APIなどで使われるポートです。開発者はこの環境に対してJavaやPythonのクライアントから接続し、基本的な送受信を確認できます。
9.2 Javaで送信する
JavaでPulsarへメッセージを送るには、Pulsarクライアントを作成し、送信者を作成し、対象トピックへメッセージを送信します。Javaは企業システムで広く使われているため、注文処理、決済処理、在庫管理などのバックエンドサービスからPulsarへイベントを送る場面でよく利用できます。
送信者を実装するときは、単に send を呼ぶだけでなく、送信失敗時の扱いを考える必要があります。重要なイベントであれば、送信に失敗したときにログを出すだけでは不十分です。再試行するのか、エラーとして処理を止めるのか、別の保存場所へ退避するのかを決めておく必要があります。
Java送信者のコード例
import org.apache.pulsar.client.api.PulsarClient;
import org.apache.pulsar.client.api.Producer;
import org.apache.pulsar.client.api.Schema;
public class OrderProducer {
public static void main(String[] args) throws Exception {
PulsarClient client = PulsarClient.builder()
.serviceUrl("pulsar://localhost:6650")
.build();
Producer<String> producer = client.newProducer(Schema.STRING)
.topic("persistent://public/default/order-events")
.create();
producer.send("order_id=1001,status=created,total=5000");
producer.close();
client.close();
}
}
このコードでは、order-events という永続トピックへ注文イベントを送信しています。実務では、このような文字列ではなく、JSON、Avro、Protocol Buffersなどの構造化データを使うことが多いです。さらに、スキーマ管理を組み合わせることで、受信側が期待するデータ形式を維持しやすくなります。
9.3 Javaで受信する
Javaでメッセージを受信するには、Pulsarクライアントから受信者を作成し、トピックと購読名を指定して購読します。受信者はメッセージを受け取り、処理が成功したら確認応答を返します。確認応答を返すことで、Pulsarはその購読においてメッセージが処理済みであると判断します。
受信処理では、例外処理が非常に重要です。処理中にデータベース書き込みが失敗したり、外部APIがタイムアウトしたりすることがあります。その場合、確認応答を返してしまうと、実際には処理できていないのに処理済み扱いになります。逆に、失敗時に確認応答を返さなければ、再配信される可能性があります。そのため、成功時と失敗時の扱いを明確に分ける必要があります。
Java受信者のコード例
import org.apache.pulsar.client.api.Consumer;
import org.apache.pulsar.client.api.Message;
import org.apache.pulsar.client.api.PulsarClient;
import org.apache.pulsar.client.api.Schema;
public class OrderConsumer {
public static void main(String[] args) throws Exception {
PulsarClient client = PulsarClient.builder()
.serviceUrl("pulsar://localhost:6650")
.build();
Consumer<String> consumer = client.newConsumer(Schema.STRING)
.topic("persistent://public/default/order-events")
.subscriptionName("order-worker-sub")
.subscribe();
while (true) {
Message<String> message = consumer.receive();
try {
String value = message.getValue();
System.out.println("received: " + value);
consumer.acknowledge(message);
} catch (Exception e) {
consumer.negativeAcknowledge(message);
}
}
}
}
このコードでは、メッセージ処理に成功した場合は acknowledge を呼び、失敗した場合は negativeAcknowledge を呼んでいます。実務では、重複処理を避けるために、注文IDなどの一意キーを使って処理済みチェックを行うことが多いです。メッセージング基盤では再配信が起こり得るため、受信側は同じメッセージが複数回来ても安全に処理できるようにする必要があります。
9.4 Pythonで送受信する
PythonでもPulsarクライアントを使ってメッセージを送受信できます。Pythonはデータ分析、検証、軽量な連携処理でよく使われるため、Pulsarに流れるイベントを簡単に確認したり、分析用の処理を作ったりする場合に便利です。小さなスクリプトで送信者や受信者を作れるため、学習にも向いています。
ただし、本番でPython受信者を動かす場合は、接続の再確立、例外処理、ログ出力、監視、プロセス管理を考える必要があります。サンプルでは無限ループで受信していますが、実際には停止処理、シグナル処理、メトリクス送信、処理時間の監視などを追加するべきです。Pythonは手軽ですが、運用設計を省略してよいわけではありません。
Python送信者のコード例
import pulsar
client = pulsar.Client("pulsar://localhost:6650")
producer = client.create_producer(
"persistent://public/default/user-events"
)
producer.send(
"user_id=42,action=login,device=mobile".encode("utf-8")
)
client.close()
Python受信者のコード例
import pulsar
client = pulsar.Client("pulsar://localhost:6650")
consumer = client.subscribe(
"persistent://public/default/user-events",
subscription_name="user-event-sub"
)
while True:
message = consumer.receive()
try:
data = message.data().decode("utf-8")
print("received:", data)
consumer.acknowledge(message)
except Exception:
consumer.negative_acknowledge(message)
このPythonコードでは、ユーザーイベントを送信し、別の処理で受信しています。実際の業務では、受信したイベントをデータベースへ保存したり、分析基盤へ転送したり、条件に応じて別トピックへ再送したりします。簡単なコードでもPulsarの基本的な流れを確認できるため、初期学習には非常に有効です。
9.5 管理コマンドを使う
Pulsarでは、管理コマンドを使ってトピック、名前空間、スキーマ、権限、Functions、IOコネクタなどを操作できます。開発者は送受信コードだけでなく、管理コマンドも理解しておくと、検証や障害調査がしやすくなります。たとえば、トピック一覧を確認したり、購読状態を見たり、スキーマを登録したりできます。
本番環境では、管理コマンドを手作業で実行するよりも、構成管理や自動化に組み込む方が安全です。誰がいつ何を変更したかを追跡できるようにし、誤操作を防ぐ仕組みを作る必要があります。特にトピック削除、権限変更、保持期間変更は影響が大きいため、レビューと承認を通す運用が望ましいです。
トピック一覧を確認するコード例
bin/pulsar-admin topics list public/default
このコマンドは、public/default 名前空間に存在するトピックを一覧表示します。検証環境では頻繁に使う基本的な操作ですが、本番環境では権限が必要になる場合があります。管理操作を誰でも自由に実行できる状態は危険なので、運用環境では認証と権限管理を必ず設定するべきです。
10. Apache Pulsarのスキーマ管理
スキーマ管理は、Pulsarに流れるメッセージの構造を安全に管理するための機能です。イベント駆動システムでは、送信側と受信側が同じデータ形式を前提に動きます。もし送信側が項目名や型を勝手に変更すると、受信側の処理が失敗したり、誤ったデータを保存したりする危険があります。
Pulsarのスキーマ管理を使うと、トピックに対してデータ構造を定義し、送信時や受信時に形式を確認しやすくなります。特に、複数チームが同じイベントを利用する環境では、スキーマはサービス間の契約のような役割を持ちます。スキーマを正しく運用することで、イベント基盤の信頼性を高められます。
10.1 スキーマが必要な理由
スキーマがない状態では、メッセージの中身は単なる文字列やバイト列として扱われます。送信側が「この項目は必ず入っている」と思っていても、受信側が同じ理解をしているとは限りません。また、開発が進むにつれて項目が追加されたり、型が変わったりすると、下流システムが壊れる可能性があります。
スキーマを使えば、メッセージの項目、型、構造を明確にできます。たとえば、注文イベントには注文ID、ユーザーID、金額、状態、作成時刻が含まれると定義できます。受信側はその定義を前提に処理を作れるため、暗黙の約束に頼る必要が減ります。長期的に運用するイベント基盤では、スキーマ管理はほぼ必須の考え方です。
10.2 スキーマ登録
Pulsarでは、管理コマンドや管理APIを使ってスキーマを登録できます。スキーマを登録しておくと、トピックに流れるデータの形式を管理でき、意図しない形式のメッセージが混ざるリスクを減らせます。特に、複数のアプリケーションが同じトピックへ送信する場合、スキーマ登録はデータ品質を守るために重要です。
スキーマ登録は、開発者が手作業で行うよりも、継続的デリバリーの流れに組み込むのが理想です。コード変更とスキーマ変更を同じレビューで確認し、互換性があるかをチェックしてから本番へ反映します。これにより、送信側の変更が受信側を壊す事故を減らせます。
スキーマ登録のコード例
pulsar-admin schemas upload \
--filename order-schema.json \
persistent://public/default/order-events
このコマンドでは、order-schema.json に定義されたスキーマを注文イベントのトピックへ登録します。実務では、スキーマファイルもアプリケーションコードと同じようにバージョン管理します。誰がどの項目を追加したのか、どの時点で互換性が変わったのかを追えるようにすることが大切です。
10.3 スキーマ互換性
スキーマ互換性とは、新しいスキーマが既存の受信者を壊さないかを判断する考え方です。たとえば、新しい任意項目を追加するだけなら問題になりにくいですが、既存項目を削除したり、文字列型を数値型へ変えたりすると、受信側が失敗する可能性があります。イベント基盤では、送信側より受信側の数が多いことがあるため、互換性は非常に重要です。
スキーマ互換性を意識しないと、あるサービスの変更が、関係者の知らない下流サービスを壊すことがあります。特に分析、監査、通知、機械学習など、同じイベントを別用途で使っている場合、送信側が把握していない受信者が存在することもあります。スキーマ変更は、単なる内部実装変更ではなく、データ契約の変更として扱うべきです。
10.4 スキーマ検証
スキーマ検証を有効にすると、登録されたスキーマに合わないメッセージの送信を防ぎやすくなります。これにより、壊れたデータがトピックへ流れ込み、下流の処理を巻き込んで障害になるリスクを下げられます。イベント基盤では、一度壊れたデータが流れると、多くの受信者が影響を受けるため、入口で検証することが重要です。
ただし、スキーマ検証を厳しくしすぎると、開発や実験がしにくくなる場合もあります。そのため、本番の重要トピックでは厳格にし、検証用や実験用の名前空間では少し柔軟にするなど、用途ごとにルールを分けると運用しやすくなります。スキーマ管理は、品質と開発速度のバランスを取りながら設計する必要があります。
10.5 スキーマ運用のコツ
スキーマ運用では、破壊的変更を避けることが基本です。項目を追加する場合は、既存の受信者が無視できる形にし、項目を削除したい場合は、まず使われていないことを確認し、段階的に移行します。型変更や意味変更は特に危険なので、新しい項目として追加し、受信者が移行した後に古い項目を廃止する方が安全です。
また、スキーマの変更履歴を残すことも重要です。イベント基盤は長期的に使われるため、数か月後や数年後に「なぜこの項目があるのか」「いつ追加されたのか」「どのサービスが使っているのか」を確認する場面があります。スキーマをドキュメント化し、変更レビューを行うことで、Pulsar上のデータを組織全体で安全に利用しやすくなります。
11. Apache Pulsar Functions
Apache Pulsar Functionsは、Pulsarに流れるメッセージを軽量に処理するための仕組みです。トピックからメッセージを受け取り、変換、フィルタリング、集計、別トピックへの出力などを行えます。大きなアプリケーションを別途作らなくても、Pulsarの近くで小さな処理を実行できる点が特徴です。
Functionsは便利ですが、何でも入れる場所ではありません。複雑な業務ロジック、長時間処理、大量の外部API呼び出しを含む処理は、専用サービスとして実装した方が保守しやすい場合があります。Functionsは、軽量で明確な責務を持つ処理に使うと効果的です。
11.1 Functionsの役割
Functionsの基本的な役割は、入力トピックからメッセージを読み取り、何らかの処理を行い、必要であれば出力トピックへ結果を書き込むことです。たとえば、小文字を大文字に変換する、特定条件のイベントだけを通す、ログに追加情報を付与する、エラーイベントだけを別トピックへ送るといった処理が考えられます。
このような処理をすべて専用アプリケーションとして作ると、デプロイ、監視、依存関係管理が増えてしまいます。Functionsを使えば、小さな処理をPulsarの仕組みに乗せて管理できるため、軽量なデータ加工には便利です。ただし、処理が増えすぎると全体の流れが見えにくくなるため、Functionsの用途と責務を明確にする必要があります。
11.2 Javaでの関数
JavaでFunctionsを書くと、型安全に処理を定義しやすくなります。既存のJavaプロジェクトと同じ言語で処理を書けるため、バックエンド開発チームにとって扱いやすい場合があります。特に、既にJavaでPulsar送受信を実装している環境では、FunctionsもJavaで統一すると保守しやすくなります。
JavaのFunctionsでは、入力型と出力型を明確にし、処理内容を小さく保つことが大切です。複雑な依存ライブラリを大量に読み込んだり、外部サービスへの通信を多く含めたりすると、関数の起動や実行が重くなります。Functionsは、イベントの軽い変換やルーティングに使うという考え方を守ると、安定して運用しやすくなります。
Java関数のコード例
import org.apache.pulsar.functions.api.Context;
import org.apache.pulsar.functions.api.Function;
public class UppercaseFunction implements Function<String, String> {
@Override
public String process(String input, Context context) {
if (input == null) {
return "";
}
return input.toUpperCase();
}
}
この例では、入力された文字列を大文字に変換して返しています。実務では、注文イベントの状態を変換したり、ログイベントに追加情報を付けたり、不要なイベントを除外したりする処理に応用できます。重要なのは、ひとつの関数に多くの責務を詰め込まず、何をする関数なのかを明確に保つことです。
11.3 Pythonでの関数
PythonでFunctionsを書くと、短いコードでデータ加工処理を実装できます。Pythonはデータ処理や検証で使いやすいため、ログ変換、簡単な文字列処理、軽量なフィルタリングなどに向いています。データ分析チームがPulsar上のイベントを少し加工したい場合にも便利です。
ただし、Python Functionsを本番で使う場合は、依存ライブラリ、実行環境、処理性能を確認する必要があります。Pythonは書きやすい一方で、高負荷・低遅延が求められる処理では注意が必要です。大量のイベントを処理する場合は、並列度や処理時間を監視し、遅延が増えないように設計する必要があります。
Python関数のコード例
def process(input, context):
if input is None:
return ""
return input.upper()
このPython関数は、入力文字列を大文字に変換します。サンプルとしては非常に単純ですが、Functionsの考え方を理解するには十分です。実際には、JSONを読み取って特定項目を追加したり、条件に合うイベントだけを出力したりする処理へ発展させられます。
11.4 デプロイ方法
Functionsは、Pulsarの管理コマンドを使ってデプロイできます。入力トピック、出力トピック、関数名、実行クラス、パッケージなどを指定して登録します。デプロイ後は、Pulsarの仕組みによって関数が実行され、入力トピックにメッセージが届くと処理されます。
本番では、Functionsのデプロイもアプリケーションと同じように管理するべきです。バージョン、設定、依存関係、ロールバック手順を明確にし、いきなり本番トピックへ適用しないようにします。検証環境で処理結果を確認し、問題がないことを確認してから本番へ反映する流れが安全です。
関数デプロイのコード例
bin/pulsar-admin functions create \
--name uppercase-fn \
--inputs persistent://public/default/input-topic \
--output persistent://public/default/output-topic \
--classname com.example.UppercaseFunction \
--jar target/functions.jar
このコマンドでは、入力トピックから受け取ったメッセージをJava関数で処理し、出力トピックへ書き込む構成を作っています。実務では、関数名、入力、出力、並列度、ログ設定などをきちんと設計し、誰が見ても役割が分かるようにすることが重要です。
11.5 Functionsの使いどころ
Functionsは、軽量な変換、フィルタリング、ルーティングに向いています。たとえば、注文イベントのうち高額注文だけを別トピックへ送る、ログイベントのうちエラーだけを抽出する、ユーザーイベントに簡単な属性を追加する、といった用途です。専用サービスを立てるほどではない小さな処理に使うと効果的です。
一方で、Functionsに複雑な業務フローを入れすぎると、システム全体が分かりにくくなります。どの関数で何が変換されているのかを追跡できなくなると、障害調査やデータ品質確認が難しくなります。Functionsを使う場合は、処理の責務、入力、出力、エラー時の動作をドキュメント化し、運用チームが追える状態にしておくべきです。
12. Apache Pulsar IO
Apache Pulsar IOは、Pulsarと外部システムを接続するための仕組みです。データベース、ストレージ、検索基盤、他のメッセージ基盤、分析基盤などからデータを取り込んだり、Pulsarから外部へデータを書き出したりできます。イベント基盤を中心にデータの流れを整理したい場合に役立ちます。
Pulsar IOを使うと、毎回ゼロから連携アプリケーションを作らなくても、既存のコネクタや設定で外部連携を構築できます。ただし、コネクタは魔法ではありません。接続先の障害、認証情報、処理保証、重複処理、書き込み失敗時の扱いを設計しなければ、本番で安定運用することはできません。
12.1 入力コネクタ
入力コネクタは、外部システムからPulsarへデータを取り込むための仕組みです。たとえば、データベースの変更履歴、外部メッセージ基盤、ファイルストレージ、ログ収集システムなどからデータを読み取り、Pulsarのトピックへ流します。これにより、さまざまな場所に散らばったデータをPulsarへ集約できます。
入力コネクタを使う場合、取り込むデータの意味と形式を明確にすることが重要です。単に外部データをPulsarへ流すだけでは、下流の受信者が何を受け取っているのか分からなくなります。トピック名、スキーマ、取り込み頻度、重複処理、遅延時の扱いを設計しておくことで、データ基盤として使いやすくなります。
12.2 出力コネクタ
出力コネクタは、Pulsarに流れるメッセージを外部システムへ書き出すための仕組みです。たとえば、Pulsar上の注文イベントをデータウェアハウスへ保存したり、ログイベントを検索基盤へ送ったり、監視イベントをアラート基盤へ連携したりできます。下流システムへのデータ配信を標準化しやすい点がメリットです。
出力コネクタでは、書き込み先の性能や障害に注意する必要があります。外部データベースが遅くなった場合、コネクタの処理も遅れ、購読遅延が増える可能性があります。また、書き込みに失敗したメッセージを再試行すると、同じデータが複数回書かれる場合があります。出力先の冪等性や一意制約を含めて設計することが重要です。
12.3 処理保証
Pulsar IOでは、処理保証を考える必要があります。最大一回、少なくとも一回、実質一回に近い処理など、どの程度の保証を求めるかによって設計が変わります。たとえば、ログ分析で多少の重複が許容される場合と、決済処理で重複が許されない場合では、必要な保証レベルが大きく異なります。
処理保証は、Pulsar側だけで完全に決まるものではありません。外部システムが重複書き込みに対応できるか、トランザクションを使えるか、一意キーで上書きできるかも関係します。そのため、Pulsar IOを設計するときは、コネクタの設定だけでなく、接続先システムの性質も確認する必要があります。
12.4 コネクタ設定
コネクタ設定では、入力トピック、出力先、認証情報、処理保証、並列度、エラー処理、タイムアウトなどを指定します。設定項目が多いため、手作業で管理するとミスが起きやすくなります。できるだけ設定ファイルをバージョン管理し、環境ごとの差分も明確にしておくべきです。
本番環境では、コネクタの起動状態だけでなく、処理遅延、失敗件数、再試行回数、出力先の応答時間を監視する必要があります。コネクタが動いているように見えても、実際には書き込みが失敗し続けている可能性があります。Pulsar IOは便利ですが、監視なしで使うと障害に気づきにくくなります。
出力コネクタ作成のコード例
bin/pulsar-admin sinks create \
--name sample-sink \
--inputs persistent://public/default/order-events \
--processing-guarantees ATLEAST_ONCE \
--sink-config-file sink-config.yaml
この例では、注文イベントのトピックを入力として、外部システムへ書き出す出力コネクタを作成しています。ATLEAST_ONCE は少なくとも一回の処理を意味しますが、再試行により重複書き込みが起きる可能性があります。そのため、出力先では注文IDなどの一意キーを使い、同じイベントが複数回来ても安全に扱えるようにする必要があります。
12.5 IOの設計注意点
Pulsar IOを使うと外部連携を簡単に作れますが、すべての処理をコネクタに任せると責務が曖昧になることがあります。コネクタは外部システムとの入出力に集中させ、複雑な業務変換や判断はFunctionsや専用サービスへ分ける方が保守しやすい場合があります。役割分担を明確にすることが重要です。
また、コネクタ障害時の再開方法も設計する必要があります。どこまで処理したか、失敗したメッセージをどう扱うか、再処理すると重複が起きないか、出力先が復旧したときに一気に負荷が流れ込まないかを考えます。Pulsar IOはデータ連携を便利にしますが、本番で安定させるには運用設計が欠かせません。
13. Apache Pulsarの運用設計
Apache Pulsarを本番環境で使う場合、コードを書くだけでは不十分です。クラスタ構成、監視、権限、保存期間、スキーマ、障害対応、再処理手順を最初から設計する必要があります。メッセージ基盤は多くのサービスが依存するため、問題が起きると影響範囲が広くなります。
運用設計で重要なのは、正常時だけでなく異常時を考えることです。ブローカーが落ちたらどうなるか、BookKeeperのディスクが逼迫したらどうするか、受信者が何時間も遅れたら誰に通知するか、誤ったスキーマ変更をどう防ぐかを決めておく必要があります。Pulsarの価値を活かすには、技術導入と運用設計をセットで進めるべきです。
13.1 クラスタ設計
クラスタ設計では、ブローカー数、BookKeeper数、メタデータストア構成、プロキシ構成、ネットワーク設計を決めます。検証環境では単体構成でもよいですが、本番では単一障害点を避ける必要があります。ひとつのノードが停止しても処理を継続できるように、複数ノード構成にするのが基本です。
また、クラスタ設計では現在の負荷だけでなく、将来の増加も考える必要があります。サービス数が増え、トピック数が増え、メッセージ量が増えると、最初の構成では足りなくなる可能性があります。最初から過剰な構成にする必要はありませんが、後から拡張しやすい設計にしておくことが重要です。
13.2 保存期間
保存期間は、メッセージをどれくらい保持するかを決める設定です。保存期間が短すぎると、受信者が遅れたときや再処理したいときに必要なメッセージが消えている可能性があります。逆に保存期間が長すぎると、ストレージコストが増え続け、BookKeeperの運用負荷も高くなります。
保存期間は、データの重要度と再処理要件に基づいて決めるべきです。決済や監査に関わるイベントは長めに保持し、リアルタイム分析用の一時イベントは短めにするなど、トピックや名前空間ごとに分けます。また、保存期間だけでなく、未確認メッセージが増え続ける購読がないかも確認する必要があります。
13.3 購読遅延の監視
購読遅延は、受信者がどれだけメッセージ処理に遅れているかを示す重要な指標です。送信量が増えた、受信者の処理が遅い、外部データベースが詰まっている、受信者にバグがあるなど、さまざまな原因で購読遅延は増加します。遅延が増え続ける場合、システム上はPulsarが動いていても、業務処理は遅れている可能性があります。
購読遅延は、重要な購読ごとにアラートを設定するべきです。たとえば、通知処理なら数分の遅延で問題になるかもしれませんが、夜間バッチ分析なら数時間の遅延が許容される場合もあります。すべて同じ基準で監視するのではなく、処理の重要度と許容遅延に応じてしきい値を決めることが大切です。
13.4 権限管理
Pulsarでは、誰がどのトピックへ送信できるか、誰が購読できるかを管理する必要があります。複数チームが同じクラスタを使う場合、権限管理をしないと、意図しないデータ送信や機密データの読み取りが起きる危険があります。特に個人情報、決済情報、監査ログを扱う場合は、最小権限の原則を守るべきです。
権限は、テナント、名前空間、トピックの単位で整理すると管理しやすくなります。開発環境では自由度を高くし、本番環境では厳格にするという使い分けも有効です。また、権限変更は履歴を残し、定期的に棚卸しする必要があります。使われなくなったアカウントや不要な権限を放置すると、セキュリティリスクになります。
13.5 障害対応
Pulsarの障害対応では、どの構成要素に問題があるかを切り分けることが重要です。ブローカー障害、BookKeeper障害、メタデータストア障害、プロキシ障害、受信者障害、外部システム障害では、原因も対処も異なります。事前に障害パターンを整理しておくと、実際の障害時に対応が早くなります。
障害時には、メッセージが失われたのか、保存されているが処理されていないのか、重複して処理された可能性があるのかを確認します。特に業務イベントでは、再処理が必要になることがあります。再処理手順を事前に決めておかないと、焦って手作業を行い、さらに問題を広げる危険があります。Pulsarの本番運用では、障害訓練と手順書が非常に重要です。
14. Apache Pulsarのユースケース
Apache Pulsarは、さまざまな場面で利用できます。代表的な用途には、注文処理、通知配信、ログ収集、IoTデータ処理、リアルタイム分析基盤があります。共通しているのは、複数のシステムが同じデータを必要とし、処理を直接結合したくないという点です。
Pulsarを使うことで、データの発生源と利用者を分離できます。送信側はイベントを出すだけで、受信側は必要なイベントを購読して処理します。これにより、新しい利用者を追加するときも既存の送信側を大きく変更せずに済みます。イベントを中心にシステムを広げていける点が、Pulsarの大きな利点です。
14.1 注文処理
ECサイトや予約システムでは、注文作成後に多くの処理が発生します。決済、在庫引当、配送準備、メール通知、ポイント付与、分析記録など、ひとつの注文から複数の処理が動きます。これらをすべて同期的に呼び出すと、どこかの処理が遅いだけでユーザーへの応答も遅くなります。
Pulsarを使えば、注文サービスは「注文が作成された」というイベントを送るだけで済みます。決済サービス、在庫サービス、通知サービス、分析サービスはそれぞれ独立した購読でイベントを受け取ります。もし通知サービスが一時的に停止しても、注文処理全体を止めずに済み、復旧後に通知だけを再開できます。
14.2 通知配信
通知配信では、メール、プッシュ通知、SMS、チャット通知など、複数の配信経路があります。アプリケーション本体がすべての通知処理を直接行うと、通知サービスの障害や遅延が本体機能に影響します。Pulsarへ通知イベントを送る構成にすると、本体処理と通知処理を分離できます。
また、通知配信は大量に発生することがあります。キャンペーン通知や障害通知などでは、一度に多くのメッセージを処理しなければなりません。Pulsarの共有購読を使えば、複数の通知ワーカーで処理を分散できます。失敗した通知だけ再試行する設計も作りやすくなります。
14.3 ログ収集
Pulsarは、アプリケーションログ、アクセスログ、監査ログ、エラーログの収集にも利用できます。各サービスがログイベントをPulsarへ送信し、下流で検索基盤、保存基盤、分析基盤へ配信する構成を作れます。これにより、ログの流れを統一し、複数用途で再利用しやすくなります。
ログはデータ量が非常に多くなりやすいため、トピック設計と保持期間が重要です。すべてのログを同じ扱いにすると、保存コストが増え、必要なログを探しにくくなります。重要な監査ログ、障害調査用ログ、一時的なデバッグログを分け、それぞれに適切な保存期間と配信先を設定することが必要です。
14.4 IoTデータ
IoTシステムでは、多数の機器から継続的にデータが送られます。温度、湿度、位置情報、稼働状態、異常検知情報など、さまざまなセンサーデータをリアルタイムで処理する必要があります。Pulsarを使うと、機器から送られたデータをトピックへ集約し、監視、分析、アラート、保存へ分配できます。
IoTデータでは、データ量が大きく、接続数も多くなる傾向があります。そのため、分割トピックやキー共有購読を使って負荷分散を考える必要があります。たとえば、機器IDをキーにすれば、同じ機器のデータを同じ受信者で処理しやすくなります。ただし、特定の機器や地域にデータが集中する場合は、キーの偏りにも注意が必要です。
14.5 データ分析基盤
Pulsarは、リアルタイム分析やデータパイプラインの入口としても利用できます。業務システムで発生したイベントをPulsarへ流し、分析基盤、データウェアハウス、機械学習基盤へ配信します。これにより、業務システムと分析システムを直接結合せずに済みます。
分析基盤では、同じデータを複数の目的で使うことがあります。リアルタイムダッシュボード、不正検知、レコメンド、長期保存、機械学習用特徴量生成などです。Pulsarでは、同じイベントを複数の購読で独立して読めるため、用途ごとの処理を分けやすくなります。データ活用を広げたい組織にとって、Pulsarは有力なイベント流通基盤になります。
15. Apache Pulsar導入のベストプラクティス
Apache Pulsarを導入するときは、いきなり全社規模で大きく始めるよりも、小さなユースケースから段階的に広げる方が安全です。Pulsarは高機能ですが、その分、設計と運用の考慮点も多くあります。最初に命名規則、購読設計、スキーマ管理、監視、再処理手順を決めておくことで、後から混乱しにくくなります。
導入の成功は、技術選定だけで決まりません。チームがPulsarの概念を理解しているか、障害時に対応できるか、データ形式を管理できるか、不要なトピックや購読を整理できるかが重要です。Pulsarを単なる便利なメッセージ送受信ツールとして扱うのではなく、長期的に使うイベント基盤として設計する必要があります。
15.1 小さく始める
最初からすべてのサービスをPulsarへ移行しようとすると、設計も運用も複雑になり、失敗しやすくなります。まずは、影響範囲が限定されたひとつのユースケースから始めるのが現実的です。たとえば、通知処理の非同期化、ログイベントの収集、注文イベントの分析連携など、効果が分かりやすい領域を選びます。
小さく始めることで、チームはPulsarのトピック、購読、確認応答、再配信、監視の感覚を学べます。実際に運用してみると、ドキュメントだけでは分からない課題も見えてきます。その経験をもとに、命名規則や運用手順を改善し、徐々に他のサービスへ広げる方が安全です。
15.2 命名規則を決める
トピック名、購読名、名前空間名、テナント名の命名規則は、導入初期に決めるべきです。命名が乱れると、どのデータがどのトピックを流れているのか、どの購読がどのサービスに使われているのか分からなくなります。これは、障害調査や権限管理、不要リソース削除を難しくします。
命名規則には、業務領域、環境、イベント種類、処理目的を含めると分かりやすくなります。たとえば、本番の注文作成イベントなら、環境と業務領域が分かる名前にします。購読名には、利用サービス名と処理目的を含めると、後から見ても役割を判断しやすくなります。命名は小さなことに見えますが、長期運用では非常に重要です。
15.3 重複処理を前提にする
メッセージング基盤では、同じメッセージが複数回届く可能性を前提に設計する必要があります。受信者が処理に成功した後、確認応答を返す前に落ちた場合、Pulsarはそのメッセージを未処理と判断して再配信することがあります。これは信頼性を高めるための仕組みですが、受信側が重複に弱いと問題になります。
重複処理への対策として、イベントIDや注文IDなどの一意キーを使って処理済み判定を行う方法があります。外部データベースへ書き込む場合は、一意制約や上書き処理を使い、同じイベントが複数回来ても結果が変わらないようにします。このような冪等な設計は、Pulsarに限らず、信頼性の高いイベント処理では非常に重要です。
15.4 監視を先に作る
Pulsarを本番で使うなら、アプリケーション実装と同じくらい監視設計が重要です。送信量、受信量、購読遅延、未確認メッセージ数、ブローカー負荷、BookKeeperのディスク使用量、エラー数などを可視化します。監視がない状態では、問題が起きても原因を特定できません。
特に重要なのは、購読遅延と保存容量です。購読遅延が増え続ける場合、受信者が処理に追いついていない可能性があります。保存容量が増え続ける場合、保持期間が長すぎるか、不要な購読が残っている可能性があります。監視は導入後に慌てて作るのではなく、最初の本番利用前に用意するべきです。
15.5 再処理手順を決める
イベント基盤では、過去のメッセージを再処理したい場面があります。受信側にバグがあり、一部のイベント処理が失敗していた場合や、分析ロジックを変更して過去データを再計算したい場合などです。Pulsarの永続保存を活かせば再処理を検討できますが、手順が決まっていないと危険です。
再処理では、どのトピックを、どの時点から、どの購読で、どの範囲まで処理するのかを明確にする必要があります。また、再処理によって外部システムへ重複書き込みが発生しないか、通知が再送されないか、下流システムに過剰な負荷がかからないかを確認します。再処理は強力な機能ですが、運用手順と安全対策がなければ大きな事故につながります。
おわりに
Apache Pulsarとは、分散メッセージング、イベント駆動、永続保存、柔軟な購読方式、マルチテナント管理、外部連携をまとめて扱える強力なメッセージ基盤です。送信側と受信側をゆるく分離できるため、複数サービスが連携する現代的なシステムでは大きな価値を発揮します。特に、注文処理、通知配信、ログ収集、IoTデータ、リアルタイム分析のように、同じイベントを複数用途で使いたい場面に向いています。
一方で、Apache Pulsarは高機能である分、学習コストと運用コストもあります。ブローカー、BookKeeper、メタデータストア、トピック、購読、スキーマ、保持期間、権限、監視など、考えるべきことは多いです。小規模な非同期処理だけが目的なら過剰になる場合もあるため、導入前には自社の要件と運用体制を冷静に確認する必要があります。
Pulsarを成功させるには、まず小さく始め、トピック命名、購読方式、スキーマ管理、監視、再処理手順を整備しながら段階的に広げることが重要です。単なるメッセージ送信ツールとして使うのではなく、システム全体のデータの流れを支えるイベント基盤として設計すれば、Apache Pulsarは長期的に大きな効果を発揮します。
EN
JP
KR