CAP定理 — 分断のとき、何をあきらめるか

ネットワークはいつか必ず切れます。切れたその瞬間、システムは「一貫した答えを守って応答を拒む」か「応答を続けて食い違いを許す」かの二択を迫られる ―― CAP定理が言っているのはそれだけで、それ以上でもそれ以下でもありません。分断を起こして確かめます。

1. C・A・P の正確な定義

頭文字の意味を正確に押さえるところからです。日常語と少しずつずれています。

POINT — 言葉のずれに注意 CAP の C は ACID の C(整合性制約)とは別物。また A は「稼働率 99.9%」のような運用指標ではなく「生きているノードが応答を拒まない」という理論上の性質。定理の主張は Gilbert & Lynch (2002) により「分断が起きている間、C と A を同時に満たすことはできない」という形で証明されている。

2. 分断がないとき — C と A は両立する

まず平常時。書込はレプリカへ複製され、少し待てば全ノードが同じ値になります。どのノードも応答し(A)、複製完了を待ってから応答すれば古い値も見せない(C)。分断がなければ C と A は普通に両立します。トレードオフになるのは複製を「待つ時間」だけ ―― これは最後の節(PACELC)で回収します。

平常時の複製 — 全員が同じ値に揃っていく
左の書き手が書くと、青→水色のパケットで全ノードに複製が広がります。右の読み手は複製の途中でも応答をもらえる(A)。複製時間を長くすると、読み手が「一瞬だけ古い値」を掴む瞬間が見えます — 分断がなくても遅延と一貫性の綱引きは存在するのです。

3. 分断 — 定理が牙をむく瞬間

スイッチ故障・ケーブル切断・過負荷。原因は何であれ、クラスタが互いに通信できない2つの島に割れることをネットワーク分断(network partition)と呼びます。分断が起きるかどうかはこちらでは選べません。選べるのは「起きたときにどう振る舞うか」だけです。

分断を起こしてみる — 複製が壁で消える
ノード間を行き交う点が複製メッセージ。分断ボタンを押すと赤い亀裂が走り、左右をまたぐメッセージは壁で ✕ になって届きません。左は3台(多数派)、右は2台(少数派)。この状態で書込を受け続けるとどうなるかが、次の2つの節です。
俗説訂正 — 「3つから2つを常に選ぶ」は不正確 「C・A・P から2つを選べ」という三角形の図が広く出回っているが、これは誤解を招く。P は選択肢ではなく前提 ―― 分散システムである以上、分断は必ず起こり得るので「P を捨てる」という選択は実質存在しない。そして分断がないときは C と A は両立する(上の第2節のとおり)。定理が選択を迫るのは分断が起きているあいだだけで、そのとき C か A のどちらを保つかを設計で決めておく、というのが正確な読み方。
分断発生中: C ∧ A は成立しない — どちらかを選ぶ Gilbert & Lynch (2002) による定式化。分断がなければこの制約は発動しない

4. CP を選ぶ — 一貫性を守り、可用性を諦める

CP 側の設計は「古い値・食い違う値を絶対に見せない」を優先します。定番の実現方法は前レッスンでやった過半数(クォーラム): 全 5 台の過半数 = 3 台に届く側だけが読み書きを続け、届かない少数派はエラーを返します。エラーを返す=可用性の放棄ですが、二重の「真実」が生まれることはありません。

CP の振る舞い — 多数派は継続、少数派はエラー
左のクライアントは3台(過半数)に複製できるので書込成功。右のクライアントの書込は、亀裂の向こうへ届かず 2/5 止まり → エラーが返ります。少数派側は読み取りも「古いかもしれない値」を出さないよう拒否(またはリーダーへ委譲)するのが厳密な CP。ZooKeeper・etcd・Spanner がこの系譜です。

5. AP を選ぶ — 可用性を守り、あとで衝突を解決する

AP 側の設計は「とにかく応答を返し続ける」を優先します。分断中も両方の島が書込を受け付けるので、同じキーに別々の値が書かれ得ます。分断が直った瞬間にそれが衝突として発覚し、何らかのルールで解決しなければなりません。

AP の振る舞い — 両側が受け続け、修復後に衝突を解決
分断中に左は X=みかん、右は X=バナナ を書き、どちらも「OK」をもらえます(A 維持)。分断解消後の同期で衝突が1件発覚。LWW(Last-Write-Wins)はタイムスタンプの新しい方を採用 — 簡単ですが負けた書込は黙って消えます。マージは両方残してアプリの意味で統合(買い物カートの和集合など)。Dynamo 系・Cassandra・CRDT がこの系譜です。

6. PACELC — 分断がなくても残るトレードオフ

CAP は「分断中」しか語りません。しかし第2節で見たとおり、平常時にも「複製を待つほど一貫するが遅くなる」という綱引きがあります。これを含めて整理したのが PACELC です。

if P : (A か C)    else : (L か C) 分断(P)中は可用性か一貫性か。分断がなくても(Else)、レイテンシ(L)か一貫性(C)かの選択が残る — Abadi (2012)
一歩先へ — 実システムの分類 PACELC で見ると設計思想が素直に読める。Dynamo 系(Cassandra・Riak・DynamoDB)は PA/EL:分断中も応答し、平常時も速さ優先で結果整合。Spanner や etcd・ZooKeeper は PC/EC:分断中は少数派を止め、平常時も同期複製の待ち時間を払って強い一貫性を出す。同じ「分散DB」でも、この2文字×2の立場がレイテンシもエラーの出方も決めている。

7. まとめ