アーキテクチャ●●●●○

CAP定理

分断耐性のある分散システムは、一貫性と可用性を同時には完全に満たせないという定理。

概要

CAP定理は、データを複数のノードに複製する分散システムが、「一貫性(Consistency)」「可用性(Availability)」「分断耐性(Partition tolerance)」という三つの性質を、同時にすべて完全には満たせないことを述べた定理です。三つの頭文字を取ってCAPと呼ばれ、提唱者の名から「ブリュワーの定理」とも言います。

三つの性質はそれぞれ、一貫性は「どのノードに読みに行っても常に最新の同じ値が返る」こと、可用性は「生きているノードはどんなリクエストにも必ず(エラーではなく)応答する」こと、分断耐性は「ノード間の通信が途切れてもシステムが動き続ける」ことを指します。よくある誤解ですが、CAPは「三つのうち好きな二つを選べる」という話ではありません。実務上ネットワーク分断は避けられない前提なので、本当に迫られる選択は「分断が起きた瞬間に、一貫性と可用性のどちらを犠牲にするか」という二者択一です。

この定理は、分散データストアを選定・設計するときの「そもそも何を諦める設計なのか」を見抜くためのレンズになります。RDBMSのレプリケーション構成からNoSQLまで、分散の背後には必ずこのトレードオフが潜んでいます。

なぜ生まれたか

分散データベースを設計する現場では、長らく「速くて、いつでも応答して、しかも常に正しい値を返す」システムを漠然と目指していました。しかし1台のマシンならACID特性のもとで自然に成り立っていた「常に正しい値」は、データを複数ノードに複製した途端に自明ではなくなります。あるノードへの書き込みが他ノードに伝わる前に別のノードが読まれれば、古い値が返るからです。

2000年、エリック・ブリュワーはこの直感を「一貫性・可用性・分断耐性は同時に満たせない」という予想として定式化し、2002年にギルバートとリンチが厳密に証明しました。これにより、「あれもこれも」という願望ではなく「分断時に何を捨てるか」を意識的に選ぶことが、分散システム設計の出発点だと共有されるようになりました。CAP定理の価値は、達成不可能な理想を追うのをやめさせ、トレードオフを直視させたことにあります。

詳細

分断が起きた瞬間の二者択一

CAP定理の核心は、ネットワーク分断が発生した「その瞬間」に現れます。分断とは、ノード自体は生きているのにノード間の通信だけが途切れる状況です。データが2台に複製されていて、その間の通信が切れたと想像してください。片方のノードに書き込みリクエストが届いたとき、そのノードは相手に変更を伝えられません。ここで採れる道は二つしかありません。

一つは「書き込みを受け付ける(可用性を守る)」道です。応答は返せますが、もう片方のノードは古い値のままなので、一貫性は崩れます。もう一つは「書き込みを拒否してエラーを返す(一貫性を守る)」道です。食い違いは防げますが、応答しないので可用性を犠牲にします。分断耐性を確保する(=分断が起きても動き続ける)以上、この二つを両立する第三の道はない、というのがCAP定理の主張です。

ネットワーク分断ノード間の通信が途切れる書き込みが片方に届いた。相手に伝えられない一貫性を守る(CP)書き込みを拒否してエラーを返す古い値は絶対に返さない→ 可用性を犠牲例: 決済・在庫・銀行残高可用性を守る(AP)書き込みを受け付けて応答する片方は古い値のまま→ 一貫性を犠牲例: SNS・カート・いいね数
ネットワーク分断が起きた瞬間、CとAのどちらを守るかの分岐

CP型とAP型 — 何を選ぶか

一貫性を優先する設計を「CP型」と呼びます。分断時には応答を止めてでも間違った値を返さない方針で、銀行の残高、在庫数、決済のように「古い値を見せると事故になる」領域が該当します。過半数のノードで合意(コンセンサス)が取れないと書き込みを認めないような強一貫の分散ストアはこちらです。

可用性を優先する設計が「AP型」です。分断時にもとにかく応答を返し、食い違いは分断が解消した後に埋め合わせます。SNSのタイムライン、ショッピングカート、いいね数のように、「一時的に少し古くても支障が小さく、それより止まらないことが大事」な領域に向きます。AP型は分断解消後に各ノードの値を収束させる結果整合性とセットで語られるのが定番です。

分断が「無い」ときの姿 — PACELC

重要なのは、CAPが語るのはあくまで「分断が起きている間」の話だということです。ネットワークが正常なときは、多くのシステムが一貫性と可用性を両立できます。このため近年は、CAPを補って「分断時(Partition)はAかCか、そうでない平常時(Else)は遅延(Latency)か一貫性(Consistency)か」を問うPACELCという枠組みで整理されることも増えました。平常時ですら、全ノードの同期を待つ強一貫は応答が遅くなり、待たない設計は速い代わりに一貫性が緩む、というトレードオフが常につきまとうからです。

実務で誤解しないために

CAP定理でよくある誤りは、三つを対等な選択肢だと思い込むことです。実システムでは分断耐性は捨てられない(ネットワークはいつか必ず切れる)ため、現実の設計判断は「分断時にCとAのどちらを取るか」に集約されます。また、CAPの一貫性は「常に最新の同一値」という非常に強い定義であって、ACIDの一貫性(制約を壊さない)とは別物である点も混同しがちです。さらに、一つのシステム全体で一律にCP・APを決める必要はなく、機能ごとに「残高照会はCP、通知はAP」と使い分けるのが実践的です。CAP定理は答えを与える道具ではなく、「あなたの選択は何を諦めているのか」を毎回突きつけてくれる問いだと捉えるのがよいでしょう。