Dev Study
← 分散システムの土台
レッスン 5 / 13·約 9 分·第12期 分散システムの土台

見えるのは遅れた信号だけ — 他ノードの状態は直接には測れない

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け今ここ
  5. Nginx受け口
  6. アプリ処理
  7. DB保存

前回はタイムアウトという1つの信号から故障を決められないことを見ました。今回は一段さかのぼり、他ノードの状態を直接観測する手段が無いことを扱います。

まず結論

他ノードの「いまの状態」を直接見る手段はありません。届くのは、相手が過去に送り出した信号と、それが来ないという事実だけです。

そして「あれは落ちている」という判定は、受け取った側が下したものです。クラスタの総意ではありません。

? 読む前に予測

監視項目を増やし、送信間隔を短くしていけば、他ノードの「いまの状態」に近づけますか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

届くのは状態ではなく、状態について送られた信号

前回、タイムアウトから故障を決められないことを見ました。今回はその手前を扱います。そもそも、他ノードの状態を直接観測する手段がありません。

1台の中でなら、値はメモリを読めば分かります。読んだ瞬間の値です。相手が別のマシンになると、こう変わります。

  1. 相手が、自分の状態から値を作る
  2. その値を信号として送り出す
  3. 信号が経路を通る
  4. 手元に届く

手元で読めるのは 4 の時点ですが、値が作られたのは 1 の時点です。この2つの時点は決して一致しません。 どんな監視を入れても、読んでいるのは過去の値です。

ここに Google SRE Book 第23章の前提を重ねます。同章が扱う非同期の合意問題は、こう定義されています。

asynchronous distributed consensus, which applies to environments with potentially unbounded delays in message passing.

遅延に上限が無い、という前提です。上限が無いなら、届いていない信号について「もう来ない」とは言えません。まだ経路にいるだけかもしれないからです。「まだ来ていない」と「二度と来ない」は、有限時間では区別できません。 これが「直接には見えない」の中身です。

手元に届くまでに何が挟まっているか
相手の状態読む手段は手元に無い
相手が値を作る(何を代理させるかはここで決まる)
代理指標の値状態そのものではない
送り出す・経路を通る(遅延に上限は無い)
届いた信号作られた時点の値
受け取った側が解釈する
生死の判定下したのは受け取った側
  • ・下へ進むたびに、元の状態から離れていく
  • ・信号が来ない場合、この列は2段目で止まる
具体実物

Cassandra は、誰が判定を持っているかを明記している

文書で確かめます。Apache Cassandra の Dynamo ページには、生死の判定についてこうあります。

Gossip forms the basis of ring membership, but the failure detector ultimately makes decisions about if nodes are UP or DOWN. Every node in Cassandra runs a variant of the Phi Accrual Failure Detector, in which every node is constantly making an independent decision of if their peer nodes are available or not.

さらに同じページに、この一文があります。

UP and DOWN state are local node decisions and are not propagated with gossip.

伝播するのはハートビートという信号のほうで、生死の判定は伝播しません。 各ノードが、自分に届いた信号だけを材料に独立に決めています。

Cassandra で伝播するもの・しないもの(Dynamo ページより)表
対象 gossip で伝播するか 誰が持つか
ハートビートの状態 する 送り出したノード発
UP / DOWN の判定 しない 判定を下した各ノード

結果として、同じ相手について、ノードごとに違う判定が同時に存在しえます。 「あのノードは落ちている」は、そう言った1台の意見です。これを取り違えると、そう報告した側を探さないまま、対象ノードのログばかり読むことになります。

✓ ここまでの確認

メッセージ遅延に上限がない前提のもと、「信号が来ない」ことから何が言えますか。

抽象原理

監視を増やしても、増えるのは代理指標の本数

一般化します。相手の状態を直接読めない以上、手元に置けるのは代理指標だけです。第29週『負荷分散の選び方 — どの実体へ配るか』で、接続数が負荷の代理指標であって負荷そのものではないことを見ました。あれは1つの場面の話でしたが、同じ形はもっと広く成り立ちます。

  • 接続数は、負荷の代理
  • CPU 使用率は、捌けているかどうかの代理
  • ハートビートの到着は、生存の代理

どれも「相手が値を作って送り出したもの」です。項目を増やすと代理指標の本数が増えますが、どれもやはり過去の値です。 頻度を上げれば手元の値は新しくなりますが、送信より後に届くことは変わりません。

もう一つ、沈黙は信号ではありません。 何も届かないという事実は、遅いのか、落ちたのか、経路が切れたのかのいずれとも整合します。だから実装は必ず「ここまで待って来なければ、来なかったことにする」という打ち切りの規則を持ちます。事実を確定させる手続きではなく、待つのをやめると決める手続きです。

具体実物

対比例 — etcd は、待つ長さを RTT に対して決めている

別の層で同じ事情が現れる例を見ます。etcd の Tuning ページは、待ち時間の決め方をこう書いています。

Election timeouts must be at least 10 times the round-trip time so it can account for variance in the network. For example, if the round-trip time between members is 10ms then the election timeout should be at least 100ms.

注目したいのは、基準が相手の状態ではなく信号の往復時間だという点です。相手が生きているかを測る値が手元に無いので、代わりに「信号がどれくらいばらついて届くか」を基準にしています。同じページの Time parameters 節には既定値の記述もあります。

By default, etcd uses a 100ms heartbeat interval.

By default, etcd uses a 1000ms election timeout.

そして同ページには、長く取ることの代償も書かれています。

Higher election timeout takes longer time to detect a leader failure.

etcd v3.5 Tuning に書かれている値(2026-09-18 取得)表
項目 値 意味
heartbeat interval 100ms(既定) 信号を送り出す間隔
election timeout 1000ms(既定) これを過ぎたら選挙を始める
election timeout の下限 RTT の10倍以上 ばらつきを見込むため

ばらつきを吸収するほど検知は遅くなります。この綱引きが起きるのは、相手の状態を直接読めず、届く信号のばらつきしか手掛かりが無いからです。 相手のメモリを読めるなら、10倍という係数は要りません。

なお、遅れた信号で増減を制御すると行き過ぎと揺り戻しが起きます。その帰結は仮想化編『オートスケールは何を見て増やすか — 測定・判断・起動の遅れ』で扱っています。今回の主題はその手前、なぜ信号しか無いのかです。

✓ ここまでの確認

Cassandra で「あるノードが DOWN だ」と判定されたとき、その判定はどこにありますか。

⇄ 2つを見比べる
具体例 A

Cassandra の UP / DOWN 判定

各ノードはハートビートの到着を材料に、相手が使えるかを独立に決めます。判定は gossip で配られないため、同じ相手への判定が同時に食い違いえます。

何が届き、何が決まるか表
届くもの ハートビートの状態(gossip 経由)
決めるもの UP / DOWN(各ノードが独立に)
判定の在り処 判定を下したノードの中だけ
具体例 B

etcd の election timeout

フォロワーは通信が途絶えたかを待ち時間で決めます。基準は相手の状態ではなく往復時間で、ばらつきを見込んで10倍以上を取るよう書かれています。長く取るほど検知は遅れます。

何を基準に、何を決めているか表
届くもの heartbeat(既定 100ms 間隔)
決めるもの 選挙を始めるかどうか
基準 RTT の10倍以上(ばらつき込み)

ノードの生死を各自が決める仕組みと、待ち時間を往復時間から決める仕組み。共通している構造は何でしょうか。

どちらも「相手の何を読んでいるか」を考えてみてください。読めていないものは何でしょうか。

この章のまとめ

  • 他ノードの状態を直接読む手段は無い。届くのは過去に送り出された信号だけ。
  • SRE Book 第23章の前提は遅延に上限が無い環境。「まだ来ていない」と「二度と来ない」を有限時間で区別できない。
  • Cassandra は UP / DOWN を local node decisions と明記する。判定は各ノードの意見。
  • 監視項目を増やしても増えるのは代理指標の本数で、過去の値なのは変わらない。
  • etcd は待ち時間を往復時間のばらつきから決める。長く取るほど検知が遅れる。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

「他ノードの状態が直接には見えない」ことの、形式的な言い換えとして最も適切なのはどれですか。

用語集(4語)
非同期モデル
メッセージ受け渡しの遅延に上限を置かない前提。Google SRE Book 第23章は "potentially unbounded delays in message passing" と表現し、上限がある前提(同期)は時間保証のある実時間システムに当たると対比している。
代理指標
見たい量そのものを測れないときに代わりに測る量。接続数を負荷の代わりに、ハートビートの到着を生存の代わりに使う、など。置き換えが破綻するまで、代理であることは表に出ない。
ローカルな決定
あるノードが自分の観測だけで下した判定。Cassandra の公式文書は UP / DOWN をこれに当たるものとし、gossip では伝播しないと明記している。同じ相手への判定がノードごとに違いうる。
election timeout
etcd で、フォロワーが選挙を始めるまでの待ち時間。公式の既定は 1000ms。ばらつきを見込んで RTT の10倍以上にするよう書かれている。