1 分

分散データベース:一貫性と可用性のトレードオフ

分散データベースが障害時に可用性を維持するために一貫性を緩める理由、CAPやクォーラムの仕組み、各アプローチを選ぶタイミングを解説。

分散データベース:一貫性と可用性のトレードオフ

一貫性と可用性が現場で意味すること

データベースが複数のマシン(レプリカ)に分散されると、速度と耐障害性が得られる一方で、機械同士が完全に一致しない、あるいは確実に通信できない期間が生じます。

一貫性(平易な意味)

一貫性とは: 成功した書き込みの後、誰が読んでも同じ値が返ること を意味します。プロフィールのメールアドレスを更新したら、次の読み取りはどのレプリカに当たっても新しいメールを返すべきです。

実務では、整合性を優先するシステムは故障時に矛盾した答えを返さないように、いくつかのリクエストを遅らせたり拒否したりします。

可用性(平易な意味)

可用性とは: システムがすべてのリクエストに応答すること を意味します。いくつかのサーバーがダウンしているか切断されていても、応答は返ってきます。最新のデータが得られないことはありますが、回答は得られます。

実務では、可用性を優先するシステムはレプリカ間で意見が分かれている間でも読み書きを受け入れ、後で差分を修復します。

そのトレードオフが実アプリに意味すること

トレードオフとは、すべての障害シナリオで両方を最大化できないことを意味します。レプリカが協調できない場合、データベースは次のどちらかを選ばなければなりません:

  • 単一の合意された真実を守るために一部のリクエストを待たせる/失敗させる(整合性を重視)、または
  • 古い/競合するデータのリスクを受け入れて応答を継続する(可用性を重視)

単純な例:ショッピングカート vs 銀行振替

  • ショッピングカート: 別のデバイスでカウントが一時的に1つずれても煩わしい程度で済むことが多い。多くのチームは高い可用性を選び、後で整合させる。\n- 銀行振替: 500ドルを移したのに残高が一時的に二つの異なる値を示すのは重大な問題。ここでは強い整合性が時折の「もう一度試してください」エラーより価値が高い。

ベストな選択は一つではない

どのバランスが良いかは、許容できる誤り(短時間の停止か、短期間の誤った/古いデータか)によって決まります。多くの実システムはその中間を選び、トレードオフを明示します。

分散がルールを変える理由

データとサービスを複数のノードで保管・提供するデータベースを「分散」と呼びます。アプリケーションからは一つのデータベースのように見えるかもしれませんが、内部では異なる場所の異なるノードがリクエストを扱います。

レプリケーション:ノードを増やす理由

ほとんどの分散データベースはデータを複製します:同じレコードが複数のノードに保存されます。これを行う目的は:

  • マシンが故障してもサービスを稼働させるため
  • 近いノードから応答してレイテンシを下げるため
  • 読み取り(と場合によっては書き込み)をスケールさせるため

レプリケーションは強力ですが、同時に「二つのノードが同じデータを持っているとき、常に一致させるにはどうするか?」という疑問を生みます。

部分的な障害は例外ではなく常態

単一サーバーでは「死んでいるか生きているか」は比較的明白です。分散システムでは障害は部分的に起こります。あるノードは立っているが遅いかもしれない。ネットワークリンクがパケットを落とすかもしれない。ラック全体が接続を失うこともあります。

ノードは別のノードが本当に落ちているのか、一時的に到達不能なのか、単に遅れているだけなのかを即座に知ることができません。調べている間に、入ってくる読み書きにどう対応するかを決めなければなりません。

通信が保証されないときに保証も変わる

単一サーバーでは一つの真実源があり、すべての読み取りは最新の成功した書き込みを見る。\n\n複数のノードでは「最新」は協調に依存します。もし書き込みがノードAで成功したがノードBに届かない場合、データベースは:

  • Bの確認を待って書き込みをブロックする(整合性を守る)、または
  • 書き込みをすぐに受け入れる(可用性を守る)

この緊張関係が、分散によってルールが変わる理由です。

ネットワーク分割:核心の問題

ネットワーク分割とは、本来一体として動くべきノード間の通信が断たれることです。ノードは稼働していてもメッセージを確実に交換できないことがあります。原因は壊れたスイッチ、過負荷のリンク、誤ったルーティング、ファイアウォール設定ミス、クラウドの“ノイジー”な隣人など多岐にわたります。

大規模では分割が避けられない理由

システムが複数のマシン(ラック、ゾーン、リージョン)に広がると、それらの間のすべての経路を制御できなくなります。ネットワークはパケットを落とし、遅延を生み、時に“島”に分かれます。小規模では稀でも、大規模では日常的に発生します。短時間の中断でも重要です。データベースは何が起きたかを常に合意する必要があるからです。

分割が生む「最新」の不一致

分割中、両側はリクエストを受け続けます。両側で書き込みが可能なら、片方の更新をもう片方が見ていないまま別の更新を受け入れることがあります。

例:ノードAが住所を「New Street」に更新し、同時にノードBが「Old Street Apt 2」に更新したとします。各側は自分の書き込みが最新だと考えます——リアルタイムで比較する手段がないからです。

ユーザーに見える症状

分割はわかりやすいエラーメッセージとして出るとは限りません。次のような混乱した動作として現れます:

  • タイムアウト:データベースが書き込みや読み取りのために他のノードの確認を待つ。\n- 古い読み取り:更新を見逃したレプリカに当たって古いデータが返る。\n- スプリットブレイン:どの側に接続したかでユーザーが異なる“真実”を見る。

この状況が圧力点になり、ネットワークが通信を保証できないときに分散データベースが整合性を優先するか可用性を優先するかを決める必要が生じます。

ジャーゴン抜きのCAP定理

CAPはデータベースを複数の機械に分散したときに起きることをコンパクトに表現する方法です。

3つの用語(平易に)

  • Consistency (整合性, C): 書き込みの後、後続の読み取りはその同じ値を返す。\n- Availability (可用性, A): いくつかのサーバーに問題があっても、すべてのリクエストにエラーでない応答を返す。\n- Partition tolerance (分割耐性, P): ネットワークが分割してノード間の通信が不確実でもシステムが動き続ける。

重要な要点

分割がないときは、多くのシステムが整合性と可用性の両方を満たすように見えます。\n\n分割があるときは何を優先するかを選ぶ必要があります:

  • 整合性を選ぶ: サーバーが合意するまで一部のリクエストを拒否または遅らせる。\n- 可用性を選ぶ: 分割の各側でリクエストを受け入れ、答えが一時的に不一致になるリスクを許容する。

想像しやすいタイムライン

  • 10:00 クライアントが balance = 100 をサーバーAに書き込む。\n- 10:01 ネットワーク分割:サーバーAがサーバーBに到達できなくなる。\n- 10:02 クライアントがサーバーBから読み取る。\n - 整合性を優先するなら、サーバーBは拒否または待機する。\n - 可用性を優先するなら、サーバーBは応答するが balance = 80 のように古い値を返すかもしれない。

よくある誤解

CAPは「恒久的に2つだけ選べ」という意味ではありません。分割が起きたときには、整合性可用性の両方を保証することはできない――という意味です。分割がない場合は多くのシステムがほとんど両方を満たしますが、ネットワークが誤動作すると限界が露呈します。

整合性を選ぶ:得られるものと失うもの

整合性を選ぶと、データベースは「みんなが同じ真実を見る」ことを「常に応答する」より優先します。実務では、多くの場合これが強い整合性(線形化可能な振る舞い)を意味します:書き込みが確定した後の任意の後続読み取りはどこからでもその値を返す。

分割時の動作

ネットワークが分割してレプリカが協調できない場合、強整合なシステムは独立した更新を両側で安全に受け入れられません。正しさを守るために通常は:

  • リクエストをブロックする、または
  • **リクエストを拒否(エラー/タイムアウト)**する

ユーザーから見ると、いくつかのマシンは稼働していてもサービスが停止しているように見えることがあります。

得られるもの

主な利点は考えやすさです。アプリケーションは複数のレプリカに対して動いているのではなく、一つのデータベースとやり取りしているかのように振る舞えます。これにより次のような「変な瞬間」が減ります:

  • 成功した更新の直後に古いデータを読むことがある
  • レプリカによって異なる値が見える
  • 競合する書き込みで不変条件を失う(例えば在庫の過販売)

監査や請求、初回から正確である必要がある処理に対しては理解しやすいモデルが得られます。

失うもの

整合性には実際のコストがあります:

  • 高いレイテンシ:多くの操作が協調(しばしばマシンやリージョン間)を待つ必要がある。\n- 障害時のエラー増加:分割や遅いレプリカ、リーダー問題がタイムアウトや「後で試してください」につながる。

製品が部分的な停止時にリクエストの失敗を許容できないなら、強整合は高価に感じられることがあります—それでも正しさのためには必要な場合があります。

可用性を選ぶ:得られるものと失うもの

例をデモに変える
カート、残高、リトライをモデル化して、実際の障害パターンを早期に把握します。

可用性を選ぶと、単純な約束を最適化します:システムは応答する。実務での「高可用性」は「エラーが全くない」ことではなく、ノード故障や過負荷、ネットワーク障害時でも多くのリクエストが答えを得られることを意味します。

ネットワーク分割時の動作

分割中、レプリカは互いに通信できません。可用性優先のデータベースは通常、到達可能な側からトラフィックをさばき続けます:

  • 読み取りはレプリカが現在持っているローカルデータで応答される。\n- 書き込みはローカルで受け入れられ、接続が戻ったときにキュー化/複製される。

これによりアプリは動き続けますが、異なるレプリカが一時的に異なる真実を受け入れる可能性があります。

得られるもの

稼働率の向上が得られます:ユーザーは地域が孤立しても閲覧、カートへの追加、コメント投稿、イベント記録などが続けられます。

ストレス時により滑らかなユーザー体験が得られます。タイムアウトの代わりにアプリは「あなたの更新は保存されました」といった挙動で継続し、後で同期します。多くのコンシューマー用途や分析用途ではこのトレードオフは有効です。

失うもの

代償は古い読み取りを返す可能性です。ユーザーがあるレプリカでプロフィールを更新してすぐ別のレプリカから読むと古い値が見えることがあります。

また書き込みの競合リスクもあります。分割の両側で同一レコードが更新され、修復時にどちらが勝つかを決める必要が出てきます。どちらか一方が勝つ、フィールドをマージする、あるいはアプリ側で解決するなどのルールが必要になります。

可用性優先設計は、一時的な不一致を受け入れて製品の応答性を保ち、後で不一致を検出・修復する仕組みに投資する考え方です。

クォーラムと投票:中間の現実解

クォーラムは多くの複製データベースが一貫性と可用性を調整するために使う実用的な「投票」技術です。単一のレプリカを信用する代わりに「十分な数」のレプリカの合意を取ります。

(N, R, W) の考え方

クォーラムはしばしば以下の3つの数で表現されます:

  • N:そのデータのためのレプリカ数
  • W:書き込みが成功と見なされるために確認が必要なレプリカ数
  • R:読み取りで参照するレプリカ数

よくある経験則は R + W > N で、これにより読み取りが最新の成功した書き込みと少なくとも1つ重なるようになり、古い読み取りの可能性が減ります。

直感的な例

N=3 の場合:

  • 単一レプリカ方式(R=1, W=1): 速く高可用だが、古いレプリカを簡単に読んでしまう。\n- 過半数投票(R=2, W=2): 書き込みは2レプリカに到達し、読み取りも2レプリカを参照する。読みと書きの集合が重なる確率が上がるため最新値を見る可能性が増える。

システムによっては W=3(全レプリカ)にして強い整合性を取るが、その場合は任意のレプリカが遅い/ダウンすると書き込み失敗が増える。

分割時のクォーラムの振る舞い

クォーラムは分割問題を消すわけではありませんが、誰が進行できるかを定義します。たとえば分割が 2–1 の場合、2側は R=2W=2 を満たせるため進行でき、孤立した1つのレプリカは進行できません。これにより競合更新は減るが、一部のクライアントはエラーやタイムアウトを見ることになります。

トレードオフ

クォーラムは通常、レイテンシ増加(より多くのノードと連絡する)、コスト増(ノード間トラフィック増)、そしてタイムアウトが可用性低下に見えるようなより微妙な障害動作をもたらします。利点は調整可能な中間点が得られることで、重要度に応じて RW を最新重視/書き込み成功重視にダイアルできます。

最終的整合性とよくある異常

最終的整合性は、レプリカが一時的に不一致でも後で同じ値に収束すれば良い、という考え方です。

具体的な例え

あるチェーンの喫茶店が共有の「売り切れ」表示を更新すると、1店舗が売り切れをマークしてもその更新が他店舗に数分遅れて届くことがあります。その間、別の店ではまだ「在庫あり」と表示されて最後の商品を売ってしまうかもしれません。システムが壊れているわけではなく、更新が追いついていないだけです。

観察される一般的な異常

データがまだ伝播中のとき、クライアントは驚くような振る舞いを経験することがあります:

  • 古い読み取り:最新の書き込みを受け取っていないレプリカから古いデータを読む。
  • 自分の書き込みが見えない:更新した直後に別のレプリカやフェイルオーバー後に自分の変更が見えない。\n- 順序の入れ替わった更新:二つの更新が異なる順序で別のレプリカに到着し、一時的に不整合なビューが生まれる。

レプリカを収束させる技術

最終的整合性システムは通常、バックグラウンドで不整合を減らす仕組みを持ちます:

  • リードリペア:読み取り時にレプリカ間の不一致を検知して古いレプリカを更新する。\n- ヒンテッドハンドオフ:レプリカがダウンしている場合、別のノードが一時的に書き込みの“ヒント”を保持して復旧時に転送する。\n- アンチエントロピー(同期):メルクルツリーやチェックサムを使った定期的な照合でドリフトを修正する。

最終的整合性が有効な場面

可用性が整合性より重要で、少し古いデータが許容できる場合に適しています:アクティビティフィード、ビューカウンタ、推薦、キャッシュされたプロフィール、ログ/テレメトリなど「しばらく後に正しくなる」ことが許されるデータです。

競合解決:分岐した書き込みの修復方法

読み書きモードをテスト
ReactアプリとGo APIを立ち上げて、厳格な書き込みと緩めの読み取りを検証します。

データベースが複数のレプリカで書き込みを受け入れると、分割中に同一アイテムに対する異なる更新が発生し競合が起きます。

典型的な例は、あるデバイスで配送先住所を更新し、別のデバイスで電話番号を同時に変更した場合です。各更新が違うレプリカに到達していると、レプリカが同期したときに「真の」レコードを決める必要があります。

ラストライトウィンズ(LWW):単純だが危険

多くのシステムはlast-write-winsを使います:最新のタイムスタンプを持つ更新が他を上書きします。

実装も簡単で計算も速いのが魅力ですが、重要なデータを黙って失う可能性があります。異なるフィールドに対する古い更新が捨てられることがあり得ますし、タイムスタンプが信用できることを前提にしているためクロックスキューで誤った勝者が選ばれることもあります。

履歴を保持する:バージョンベクターなど

安全な競合処理は因果関係の追跡を必要とすることが多いです。

概念的には、バージョンベクター(やその簡易版)が各レコードに付与され、どのレプリカがどの更新を見たかをまとめたメタデータになります。レプリカがバージョンを交換すると、あるバージョンが他を包含している(競合でない)か、分岐している(競合)かを検出できます。

一部のシステムは論理時計(Lamport時計)やハイブリッド論理時計を使い、壁時計に頼らず順序のヒントを与えることもあります。

上書きではなくマージする

競合を検出したら選択肢があります:

  • アプリレベルのマージ:アプリがフィールドをどう結合するか、ユーザーに確認するか、両方を保持するかを決める。
  • CRDT(競合回避複製データ型):カウンタや集合、協調テキストなどで自動かつ決定的にマージできるデータ構造。可用性を保ちながら“勝者総取り”を避ける。

どの方法が最適かは、そのデータにとって「正しい」とは何かで決まります—場合によっては書き込みが失われても問題ないこともありますし、重大なビジネス上の不具合になることもあります。

自分のユースケースでの選び方

整合性/可用性の姿勢を決めるのは哲学的議論ではなくプロダクトの意思決定です。まず問うべきは:「一瞬間違うことのコスト」と「『後でまた試してください』と言うコスト」はどちらが大きいか」です。

ビジネスリスクを整合性ニーズにマップする

いくつかのドメインは書き込み時に単一の正当な答えを必要とします:

  • 金銭・請求:二重請求、過剰引き落とし、返金は強い整合性が必要なことが多い。\n- IDと権限:ログイン、パスワードリセット、アクセス制御やロール変更はスプリットブレインを避けるべき。\n- 在庫やキャパシティ:過販売が許されない(チケットや限定在庫)なら整合性寄りか、明示的な予約を設計する。

逆に一時的な不一致の影響が小さい/可逆なら可用性寄りにできます。

許容できる古さを決める

多くのUXはやや古い読み取りで問題ありません:

  • フィードやタイムライン:投稿が数秒遅れて表示されても通常許容される。\n- 分析やダッシュボード:バッチ的な遅延は一般的で期待されている。\n- キャッシュや検索インデックス:「まだ更新されていない」ことは速さと安定性のために受け入れられる。

「どれくらい古くて良いか」を明確に:秒、分、時間が設計の指針になります。

ユーザーが最も嫌う障害モードを選ぶ

レプリカが合意できないとき、典型的なUXは三つになります:

  • スピナー/待ち(正確さを優先し遅く感じられる)\n- エラー/リトライ(正直だが中断的)\n- 古い結果(滑らかだが時々驚かれる)

機能ごとに最も害が少ない選択をし、グローバルに一つの方針に固定しないことが重要です。

クイックチェックリスト

整合性(C)寄りにするべきとき: 結果が間違っていると金銭的/法的リスクやセキュリティ問題、不可逆な操作になる場合。

可用性(A)寄りにするべきとき: ユーザーが応答性を重視し、古いデータが許容でき、競合は後で安全に解決できる場合。

迷ったらシステムを分割する:重要なレコードは強整合性で扱い、派生ビュー(フィード、キャッシュ、分析)は可用性最適化にする。

トレードオフの痛みを減らす設計パターン

作って共有してクレジットを獲得
Koder.aiで作ったものを共有し、他者に教えながらクレジットを稼ぎます。

システム全体で一つの「整合性設定」を選ぶ必要はほとんどありません。多くのモダンな分散データベースは操作ごとに整合性を選べます。賢いアプリはこれを使い分けて、UXを滑らかにしつつ現実を隠さない設計をします。

操作ごとの整合性レベルを使う

一貫性をダイヤルのように扱い、ユーザーの操作に応じて調整します:

  • 重要な更新(支払い、在庫減少、パスワード変更):強い整合性(例:クォーラム/線形化可能な書き込み)。\n- 重要でない読み取り(フィード、ダッシュボード、「最終アクセス」など):弱い読み取り(ローカル/1レプリカ/最終的整合性)で速度と耐障害性を確保。

これによりすべてに最高のコストを払う必要がなく、本当に必要な操作だけを保護できます。

ひとつのフローで強と弱を混ぜる

一般的なパターンは書き込みは強く、読み取りは弱くです:

  • 厳格なレベルで書き込みを行い権威ある記録を作る。\n- 読み取りは緩く行い、もし何かおかしい(項目が見つからない、カウントが古い等)なら強い読み取りで再確認するか「更新中」の表示を出す。

場合によっては逆も有効です:速い(キュー済み/最終的)書き込み確認時の強い読み取り(「注文は完了しましたか?」の確認)を組み合わせる。

リトライの設計:冪等性

ネットワークが不安定なとき、クライアントは再試行します。再試行を安全にするためにidempotency keysを使い、「注文を2回送ったら2件できる」事態を避けます。初回の結果をキーと紐づけて再利用します。

長いワークフロー:サーガと補償

複数サービスにまたがるマルチステップ操作にはサーガを使います:各ステップに対応する補償アクション(返金、予約解放、出荷キャンセルなど)を用意し、部分的な障害や一時的不一致が起きても回復可能にします。

整合性 vs 可用性のためのテストと可観測性

整合性/可用性のトレードオフは見えなければ管理できません。本番の問題は「ランダムな失敗」に見えることが多いので、適切な計測とテストを入れることが重要です。

測るべきもの(と理由)

ユーザー影響に直結する少数の指標から始めましょう:

  • レイテンシ(p50/p95/p99):フェイルオーバーやリーダー切替、クォーラム再試行時のスパイクを監視。\n- エラー率:ハードなエラー(タイムアウト、5xx)とソフトなエラー(フォールバックで返した部分結果)を分ける。\n- 古い読み取り率:ターゲットとする古さ(例:2秒以上古い)を超えた読み取りの割合。\n- 競合率:同時書き込みが原因で調整が必要になった頻度(LWWの上書きも含む)。

可能ならメトリクスに整合性モード(クォーラム vs ローカル)やリージョン/ゾーンでタグ付けして挙動の差を見つけやすくします。

あえて分割をテストする

本番の障害を待たないでください。ステージングでカオス実験を行い、以下をシミュレートします:

  • レプリカ間でのパケット落下や高遅延\n- あるリージョンが到達不能になる状況\n- 一部ノードだけが通信できるような部分分割

重要なのは「システムが稼働し続けるか」だけでなく、どの保証が維持されるかを検証することです:読み取りは新鮮か、書き込みはブロックされるか、クライアントは明確なエラーを受け取るか。

トレードオフを早期に検知するアラート

次のようなアラートを設定しましょう:

  • 許容する古さの窓を超えるレプリケーション遅延\n- クォーラム失敗(必要なレプリカに到達できない)やリトライ数の増加\n- 書き込み競合や再調整のバックログ増加

最後に、運用チームとプロダクトチームに対して通常時と分割時に何を保証するのかを文書化し、ユーザーに何が見えるかを教育しておきましょう。

CAPの選択を素早くプロトタイプする方法(すべてを再構築せずに)

新製品でこれらのトレードオフを探る際は、特に障害モードやリトライ挙動、UI上での「古さ」がどのように見えるかを早期に検証することが役立ちます。

実用的なアプローチは、ワークフローの小さなプロトタイプ(書き込み経路、読み取り経路、リトライ/冪等性、再調整ジョブ)を作って検証することです。Koder.ai のようなツールを使えば、チャット駆動のワークフローでウェブアプリやバックエンドを素早く立ち上げ、データモデルやAPIを反復し、強い書き込み+緩い読み取りのような異なる整合性パターンを本格的な構築コストなしに試せます。プロトタイプが望む振る舞いを示したら、ソースコードをエクスポートして本番へと発展させられます。

よくある質問

Why do distributed databases face a consistency vs availability trade-off?

レプリケートされたデータベースでは「同じ」データが複数のマシンに存在します。これは耐障害性や低レイテンシをもたらしますが、調整の問題も導入します:ノードは遅延したり到達不能になったり、ネットワークで分断されたりするため、常に最新の状態で合意できるとは限りません。

What does “consistency” mean in plain terms?

一貫性とは、成功した書き込みの後、どのレプリカから読んでも同じ値が返ることを意味します。実際のシステムでは、これを保証するために十分なレプリカ(またはリーダー)が更新を確認するまで読み書きを遅らせたり拒否したりすることがよくあります。

What does “availability” mean in plain terms?

可用性とは、一部のノードがダウンしたり通信できない場合でも、システムがすべてのリクエストに対してエラーでない応答を返すことを意味します。返ってくる応答は古い情報や局所的な状態に基づくかもしれませんが、障害時にユーザーをブロックしないことを優先します。

What is a network partition, and why does it matter so much?

ネットワーク分割とは、本来一つのシステムとして動作すべきノード間の通信が断たれることです。ノードは稼働しているかもしれませんがメッセージを確実に交換できないため、データベースは次のどちらかを選ばざるを得ません:

  • 単一の真実を保つためにリクエストをブロック/拒否する(整合性)、または
  • それぞれの側で応答して後で差分を調整する(可用性)。
What do users actually experience during partitions or replica disagreement?

分割中、両側で更新を受け付けられると、それぞれの側が互いに共有できない更新を受け入れることがあります。その結果として見られる現象は:

  • タイムアウト(到達不能なレプリカを待つ)
  • 古い読み取り(更新を受け取っていないレプリカから読む)
  • スプリットブレイン(どの側に接続するかで異なる“真実”が見える)

これらはレプリカが一時的に調整できないことのユーザー向けの表れです。

Does CAP theorem really mean you can only pick two out of three?

それは「永遠に2つ選べ」という意味ではありません。分割が発生したとき、整合性可用性の両方を同時に保証することはできない――という意味です。分割が無い時には、多くのシステムが両方に非常に近い振る舞いを示しますが、ネットワークが問題を起こすとその限界が露呈します。

How do quorums (N, R, W) help balance consistency and availability?

クォーラムはレプリカ間の投票によってバランスを取る現実的な手法です:

  • N = レプリカの総数
  • W = 書き込みが成功と見なされるために確認が必要なレプリカ数
  • R = 読み取りで参照するレプリカ数

一般的な目安は R + W > N で、これにより読み取りセットと直近の書き込みセットが少なくとも1つ重なるため古い値を読む確率が下がります。クォーラムは分割を無くすわけではなく、どちらの側が進行できるかを定義します(たとえば過半数を持つ側など)。

What is eventual consistency, and what anomalies should I expect?

最終的整合性は、レプリカが一時的に不整合でも時間が経てば収束することを許容するモデルです。よくある異常は:

  • 古い読み取り
  • 自分の書き込みが見えない(read-your-writesギャップ)
  • 順序の入れ替わった更新

システムは通常、リードリペアヒンテッドハンドオフ、定期的な**アンチエントロピー(差分照合)**などで不整合の窓を小さくします。

How are conflicting writes reconciled after a partition heals?

分割中に異なるレプリカが同じアイテムに別々の書き込みを受け付けると競合が起きます。解決方法の例:

  • Last-write-wins (LWW):単純だがデータを黙って失う危険があり、時計のずれに依存する。
  • バージョンベクター/因果メタデータ:どちらが包含しているかを検出して真の競合かどうかを判断する。
  • マージ/CRDT:特定のデータ型で自動的かつ決定的にマージする(カウンタや集合など)。

「正しい」とは何かで最適な戦略が変わります。場合によっては書き込みを失うことが許容されるが、重大なビジネス領域では許されません。

How do I choose the right consistency vs availability posture for my application?

ビジネスリスクと許容できるエラーの種類で決めてください:

  • 金銭や請求、権限周り、不可逆な操作は強い整合性を優先すべきです。\n- フィードや分析、キャッシュ、ログなど遅延を許容できる領域は可用性寄りで良いことが多いです。

実務的には、操作ごとに整合性レベルを変えたり、アイドンプトン性キーで安全にリトライを設計したり、長いワークフローにはサーガと補償アクションを使うことが有効です。

Related posts