Lamportの論理クロック:分散システムに「時間」を定義した論文
物理時刻に頼らず因果でイベントの順序を捉える——Lamportの論理クロックを読み解き、分散システムの並行処理・因果整合性・分散合意を支える考え方を、1本の古典論文から身につけられる。
- Lamportの1978年論文『Time, Clocks, and the Ordering of Events in a Distributed System』は、物理時計がずれる分散系の順序問題を、因果関係で定義し直した古典。
- happens-beforeは同一プロセス順・送信→受信・推移律の3規則で因果を定義する。論理時計はa→bなら時刻も増すが逆は成り立たず、並行イベントの前後は判定できない。
- この発想は、因果関係の有無まで判定できるベクタークロックへ拡張された。分散データベースの因果整合性やDynamoのバージョニングに応用され、全順序化を用いた状態機械複製は分散合意の理論的土台となって、後のPaxosへと繋がっていった。
この論文が解いた問題
横にスクロール
分散システムでは、複数のコンピュータがネットワークを介して協調する。ここで根本的な難問になるのが「どのイベントが先に起きたのか」という問いだ。1台のマシンなら内蔵時計を見れば順序は明らかに思える。だが複数のマシンが関わった途端、この直感は崩れる。
各マシンの物理時計は、水晶振動子の個体差でわずかにずれ続ける。ネットワーク越しに時刻を合わせても、通信の遅延そのものが一定しないため、完全には同期できない。結果として、マシンAが「10時00分00.100秒」と記録したイベントと、マシンBが「10時00分00.090秒」と記録したイベントのどちらが本当に先だったのかは、時計の数値だけでは判断できない。BのイベントがAへのメッセージを引き起こしていたとしても、時計のずれ次第で数値は逆転しうるからだ。
Leslie Lamportが1978年に発表した「Time, Clocks, and the Ordering of Events in a Distributed System」は、この問題に発想の転換で答えた。分散システムで本当に必要なのは「何時何分に起きたか」という絶対時刻ではなく、「どちらが原因でどちらが結果か」という因果の順序だ、と見抜いたのである。物理時刻を捨て、イベント間の関係だけから順序を定義する。それがこの論文の出発点だ。
この論文は分散システム分野で最も引用される古典の1つとなり、後続の理論と実装の土台になった。同じ系譜の題材は論文で辿るシリーズからも辿れる。
核心アイデア
happens-before という半順序
Lamportはまず、イベント間の「happens-before(先行)」関係を、記号「→」で定義した。a→b は「aがbより前に起きた」と読む。この関係は、次の3つの規則だけで決まる。
- 同一プロセス内の順序: 同じプロセスの中でaがbより先に実行されたなら、a→b。
- 送信と受信: aがメッセージの送信、bがその受信なら、a→b。
- 推移律: a→b かつ b→c なら、a→c。
この3規則の巧妙さは、物理時計をまったく使っていない点にある。プロセス内の実行順と、メッセージが送られてから受け取られるという因果の連鎖だけで、順序を組み立てる。メッセージは必ず送信が受信に先立つ——この当たり前の事実こそが、離れたマシンのイベント同士を繋ぐ唯一の糸になる。
重要なのは、これが全順序ではなく半順序だという点だ。2つのイベントaとbについて、a→bでもb→aでもない場合がありうる。互いにメッセージの連鎖で繋がっていない、独立したイベントである。これらをLamportは「並行(concurrent)」と呼んだ。並行なイベントには、本質的に前後が存在しない。どちらが先かを問うこと自体が無意味なのだ。
物理時計を捨てると、「同時」という概念も揺らぐ。あるイベントの前後が決まるのは、それが因果の連鎖で繋がっているときだけだ。繋がっていない並行イベントの前後は、観測する立場によって違って見えてよい。Lamportはこの直観を、相対性理論における同時性の相対性になぞらえて説明した。
論理クロックで順序を数値にする
半順序の定義はできた。だが実装では、各イベントに具体的な数値を振れると扱いやすい。そこでLamportは「論理クロック」を導入する。各プロセスがカウンタ C を1つ持ち、次の規則で更新する。
初期値: C = 0
規則1: イベントを起こすたびに C を1増やす
規則2: メッセージ送信時、現在の C を timestamp としてメッセージに載せる
規則3: メッセージ受信時、
C = max(自分のC, 受信した timestamp) + 1
この単純な規則が、次の性質を保証する。もし a→b なら、先に起きたイベントのカウンタは必ず後のイベントより小さくなる。なぜ効くのかは規則をたどれば分かる。同一プロセス内ではカウンタが単調に増えるので順序は保たれる。メッセージをまたぐ場合は、受信側が「送信時の timestamp より必ず大きい値」を採るよう規則3が強制する。だから因果の連鎖に沿って、カウンタは必ず増加していく。
ただし逆は成り立たない。カウンタが小さいからといって、そのイベントが原因の側だとは限らないのだ。並行なイベントにも、カウンタはたまたま大小の付いた数値を与えてしまうからである。論理クロックが表せるのは「因果があれば数値も順序どおり」という一方向の含意だけであって、数値の大小から因果を復元することはできない。ここは誤解しやすい要注意点だ。
| 主張 | 成り立つか |
|---|---|
| a→b ならば論理時刻は必ず増える | 成り立つ |
| 論理時刻が大きければ a→b といえる | 成り立たない |
| 並行イベントの前後を論理時刻で判定できる | できない |
全順序への拡張
論理クロックの値が等しいイベントは、複数ありうる。だが分散システムでは、全プロセスが1つの順序に合意したい場面もある。そこでLamportは、カウンタの値が等しいときはプロセスIDの大小でタイブレークする方法を示した。これで任意の2イベントに必ず前後が付き、半順序を全順序へと拡張できる。
この全順序化は、単なる整理術ではない。Lamportは同じ論文の中で、これを使って複数のプロセスが「同じ操作を同じ順序で適用する」仕組み——後に状態機械複製(state machine replication)と呼ばれる技法——を構築した。全プロセスが操作を同一順序で処理すれば、初期状態が同じである限り、以後の状態も常に一致する。これは分散合意(コンセンサス)の理論的な土台であり、Lamport自身が後年に生み出すPaxosへと繋がっていく着想でもあった。
その後の影響
論理クロックの「因果を数値で近似する」という発想は、その後の分散システムの広い範囲に浸透した。
第一に、ベクタークロックへの発展だ。Lamportクロックは因果があれば数値が増えることは保証するが、数値だけを見て2つのイベントが因果関係にあるのか並行なのかを判定することはできなかった。この限界を埋めるため、各プロセスの論理時刻を要素ごとに束ねた「ベクタークロック」が考案された。ベクタークロックは、2つのイベントが因果で繋がっているか、それとも並行かを完全に判定できる。Lamportクロックが残した問いへの、直接の回答である。
第二に、分散データベースの因果整合性だ。地理的に分散したデータベースでは、すべての更新に厳密な全順序を課すと性能が犠牲になる。そこで「因果関係のある更新の順序だけは守る」という因果整合性が採られる。この考え方の骨格は、まさにhappens-beforeに由来する。AmazonのDynamoが採用したバージョニングは、ベクタークロックで更新の因果を追跡し、並行に起きた競合を検出してアプリケーション側に解決を委ねる。これも系譜をたどればLamportの論文に行き着く。
第三に、分散デバッグとオブザーバビリティだ。複数のサーバーにまたがる処理を追うとき、ログを物理時刻で並べると時計のずれで順序が乱れてしまう。論理クロックやその発展形で因果順にイベントを並べ替えれば、原因と結果を正しく辿れる。分散トレーシングが親子関係でスパンを繋いでいく発想も、この延長線上にある。
「物理時刻に頼らず因果を追う」という原則は、今日のシステム設計でも実践的だ。イベントに順序番号やバージョンを持たせ、競合は物理時刻の大小ではなく因果の有無で判断する。こうした分散システムの設計原則はSystem Design側でも扱っている。
まとめ
Lamportの1978年の論文は、「分散システムに絶対時刻は要らない。必要なのは因果の順序だ」という一点を、明快に示した。happens-beforeという半順序でイベントの前後を定義し、論理クロックでそれを単調増加のカウンタへ写し取る。因果があれば数値も順序どおりになる——ただし逆は言えず、並行なイベントには本質的に前後がない。
この単純で強靭なアイデアは、ベクタークロック、因果整合性、状態機械複製、そして分散デバッグへと枝分かれし、現代の分散システムの基礎語彙になった。時間という当たり前のものを疑うことから、これほど広い理論が育った。分散システムを学ぶ者が、最初に読むべき一本である。
分散システムの論文の記事ガイド
Lamportの論理クロック:分散システムに「時間」を定義した論文を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
論文
比較で見る軸
難易度: advanced / カテゴリ: 分散システムの論文 / タグ数: 5
導入後に効く点
happens-beforeは同一プロセス順・送信→受信・推移律の3規則で因果を定義する。論理時計はa→bなら時刻も増すが逆は成り立たず、並行イベントの前後は判定できない。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- 分散システムの論文
- タグ数
- 5
判断チェックリスト
- 自社の用途が「論文 / 分散システム」に近いか確認する。
- 強みである「Lamportの1978年論文『Time, Clocks, and the Ordering of Events in a Distributed System』は、物理時計がずれる分散系の順序問題を、因果関係で定義し直した古典。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。