🧑‍✈️

分散システムにおけるノード管理とSWIMプロトコルの仕組み

に公開

はじめに

分散システムは大規模システムで採用されているスケーラブルで柔軟なアーキテクチャですが、その一方で「ノードが今も正常に動いているかどうか」を正確に把握することが難しいといった側面があります。本記事では、分散システムが抱える課題と、それに対する解決策の一つであるSWIMプロトコルについて解説します。

分散システムの課題

分散システムでは、複数のノード(コンピュータ)が連携して処理を行いますが、以下のような理想的な前提に依存すると、重大な問題が発生します。

  • ネットワークは常に信頼できる
  • レイテンシーは存在しない
  • ノードは常に応答する

現実には、ネットワークの遅延、パケットロス、ノードクラッシュは避けられません。こうした前提のもとで構築されたシステムは、障害を誤検知したり、ノード間通信の失敗により、連鎖的な障害(カスケード障害)を引き起こすリスクがあります。

状態管理のための基本手法:PingとHeartbeat

分散システムでは、各ノードの状態を管理するために、以下のようなシンプルな方法がよく用いられます。

  • Ping方式

    あるノードが他のノードに対して直接問い合わせ(ping)を行い、一定時間内に応答があるか確認します。

  • Heartbeat方式

    各ノードが定期的に「自分は生きている」という信号(ハートビート)を他のノードに送信します。

これらの方法は基本的ですが、ネットワーク環境の不確実性により「応答がない=障害」と単純に判断することは危険です。

例えば、AからCに対して、直接的にpingを送信した場合、ネットワークの混雑やパケットロスにより返答(ACK)がない状況が発生します。この時、Cが生きていても故障として誤検知(偽陽性)されてしまいます。

SWIMプロトコルとは?

SWIM(Scalable Weakly-consistent Infection-style Process Group Membership)は、スケーラブルなフォールトディテクション(障害検出)とメンバーシップ管理を目的としたプロトコルです。

SWIMは基本的にPing形式を用いていますが、Pingが失敗した場合に備えて、他のノードに間接的なPingを依頼するという仕組みを持っています。

こうすることでネットワークの一時的な不安定性による誤検知を減らせたり、ピアツーピア型でスケーラブルな設計を実現することができます。

  1. 直接Ping
  • ノードAがノードCに直接Pingを送る
  • Cが正常であれば ACK を返し、AはCが生きていると判断
  1. 応答がない場合:間接Ping(indirect ping)
  • Aは一定時間 ACK を待っても応答がなければ
  • 他のノード(例:B, D)に「ping-req」を送信し、Cへ代わりにPingさせる
  1. 応答の代理確認
  • B または D が C に直接 Ping を送り、Cから ACK を受け取れたら
  • その ACK を Aに転送(proxy ack)することで、Aは C が生きていると判断
  1. 間接Pingでも応答がない場合
  • A は C を「suspect(疑わしい)」状態としてマークし始める
  • 一定時間応答がないままなら、C を「dead(障害)」とみなす
  1. ゴシップによる情報の拡散
  • A が「Cで障害」と判断した場合、その情報を他のノードに知らせる
  • Ping/Ping-Req/Ack メッセージに状態情報を添付
    • 例:dead(C)suspect(C)
  • この情報は他のノードにも伝播され、B, Dなども C で障害があることを徐々に認識

参考

https://www.hashicorp.com/en/blog/making-gossip-more-robust-with-lifeguard?utm_source=chatgpt.com

https://en.wikipedia.org/wiki/SWIM_Protocol?utm_source=chatgpt.com

https://www.cs.cornell.edu/projects/Quicksilver/public_pdfs/SWIM.pdf?utm_source=chatgpt.com

https://youtu.be/bkmbWsDz8LM?si=ixAMsTr9JPbS6Hm2

Discussion