Re:Architect

今日よりも一歩進んだ世界を実現するためのアーキテクチャを考えます

はじめからの分散メッセージングシステム  ~Part2.分散基盤の導入~

分散メッセージング基盤と聞いて何を思い浮かべるでしょうか。
最近流行りのchatGPTに尋ねてみたところ、以下の回答が返ってきました。

分散メッセージング基盤(Distributed Messaging Infrastructure)とは、複数のコンピューターやデバイス間で情報をやり取りするためのシステムのことを指します。 分散メッセージング基盤は、分散型システムを構築する際に使用されることが多く、スケーラビリティや可用性を高めることができます。また、分散メッセージング基盤は、リアルタイムでの情報交換やデータのやり取りが必要なアプリケーションでも使用されることがあります。例えば、複数のデバイスで同期して動作するゲームや、IoT(Internet of Things)デバイスでの情報収集などです。

上記に記載の通り、データのやり取りが必要なアプリケーションで使われるような技術です。 Apache KafkaやAmazon Kinesisなんかは聞いたことがある人もいるのではないでしょうか。
本記事では単純なノード間のやり取りからはじめて、メッセージング基盤、および"分散"メッセージング基盤まで解説することを目指します。最後には主要な製品の解説も入れるつもりです。

本記事はPart2です。 以前の記事はこちら

full-house.hatenablog.com

目次

分散メッセージングシステムの導入と課題

さて、前回の記事ではメッセージングシステムの導入とその課題について説明してきました。

前回のメッセージングシステムでは以下の問題がありました。

  • 障害時の切り替えに数秒程度の時間がかかる(Active-Standbyであるため)

  • 単一サーバで処理を行うため、リソースの限界がある

  • 性能向上のためには待機系もあわせてスペックアップする必要があるため、コスト対性能比が良くない

上記の課題を解決するために「分散メッセージングシステム」が登場しました。

偉大なる先人たちは思いました、アクティブ-スタンバイがだめなら、アクティブーアクティブにすればよいじゃないかと!

またディスク装置も共有しているので、それぞれでデータを持つことにしましょう。

先ほどはメインとサブ号機があり、どちらかしか稼働していませんでしたが今回はどちらも稼働しています。

しかし、これには二つの問題があります。

  1. メッセージの順序は保証されません。
  2. どちらかが障害になった際に片方のデータは失われてしまいます。

順番が保証されない問題について

①赤、青の順番でAからメッセージが送信されました。

②それぞれ別のノードが赤と青のメッセージを受け取りました

③さて、どちらのメッセージが先にBに到着するでしょうか。

直感的には赤が最初に送ったのだからBに到着するのも赤が最初になりそうな気がしますね。

ただ赤のメッセージが通る経路が混雑していたらどうでしょう、あるいは赤のメッセージを受け取ったキューが仕事で手一杯だったらどうでしょう。

答えは送った通りの赤、青の順番で届くこともあれば、青、赤の順番で届くこともあります。

つまり「順番が保証されない」のです。

障害時のデータ保証について

こちらはイメージしやすいかと思います。前回の記事ではディスクを共有することでデータの消失を防いでいましたが、データも処理も"分散"してしまったので、障害が発生したノードが管理していたメッセージは失われてしまいます。

課題解消に向けて

先の問題を解決するためにモデルを更新しましょう。 障害時にもデータを保全できるように、ノード間で複製を行うこととしましょう。

また順序保証の仕組みのために「パーティションキー」と呼ばれる概念を導入しましょう。 モデルは以下のように更新されます。

順番が保証されない問題について

先ほどは完全にランダムに振り分けていたので、順序を保つのは難しいということでした。

そのままでは順序を保つのが難しいので、メッセージごとにそれぞれの担当を決めましょう。

担当を振り分けるためになんらかの目印が必要ですね。一般的には「パーティションキー」と呼ばれます。

図では①が青のメッセージ担当、②が赤のメッセージ担当です。

完全に順番を保証することはできませんが、少なくともパーティションキーが同じメッセージは同じノードが担当するので順序を保つことができます。

なので、順序を保ちたいメッセージは同じパーティションキーにしてあげればよいことになります、例えばIoTでの用途を考えた際に、IoTデバイスを一意に特定できるIDをパーティションキーとして設定してあげることで、異なるIoTデバイス間ではBで受け取る順番が異なる可能性がありますが、同じデバイスでは時系列が保証されます。

障害時のデータ保証について

図中の濃い色がオリジナルのメッセージ、薄い色が複製されたメッセージを表しています。 それぞれが担当するメッセージを複製して、別ノードに持たせることで単一ノード障害時にもデータを保全することが可能です。

管理者ノードの導入によるさらなる改善

さて、ここまでのモデルで十分問題ないように見えてきますね。 ただ悲しいかな、まだいくつかの問題が存在します。

例えば、②が障害により赤のメッセージを送信できなくなったらどうしましょう。

①が赤の複製メッセージを持っているので代わりに送信を担当することができますね。

あれ、この判断は自分たちでやるのでしょうか。

ほかにもユーザが新しくメッセージの振り分け定義を追加する場合はどうすればよいのでしょうか。どちらかのノードのみに変更を行えばよいのでしょうか。

上記のような種々の管理を行うために「管理者」ノードを作成することにしましょう。

管理者は便宜上の呼び名であって、本構成の一般的な呼び方ではないので注意してください。

①も②も管理者にお伺いたててから操作を実行します。

また管理者の指示によってリーダーを変更したりします。 まるで平社員と上司の関係のようですね!キューは実働(メッセージの送信を担当)し、管理者はメッセージの送信は担当しませんが、管理データを用いて指示だしを行います。

今度こそよさそうですね!

しかし、あなたはふと思うのかもしれません。これで”分散”?

管理者に頼ってる時点で完全な”分散”とは言えないんじゃないかと

次回はさらなる発展形となります。

そこで導入された概念がRaftによる分散処理です。最近の分散メッセージングシステムは上記の考え方を踏襲しているものがとても多いです。