データベース

結果整合性とは?強整合性との違いとレプリカ遅延の設計を実装者目線で解説【2026年版】

結果整合性(eventual consistency)とは、あるデータへの更新が止まりさえすれば、いずれ全てのレプリカが最後に書かれた値を返すようになる、という保証のことです。裏を返せば、更新が続いているあいだに何が読めるかは何も保証していません。書いた直後に読んで古い値が返る、さっき見えた値が次の読み取りで消える。分散データベースで「たまに古いデータが見える」と言われる現象は、ほぼ全てこの保証の緩さから来ています。この記事で扱う範囲は、保証の正確な境界、ズレが生まれる経路と修復の仕組み、DynamoDB・Cosmos DB・Cassandraでの選び方、そしてアプリ側でこの穴を塞ぐ実装までです。複製方式そのものの選定は同期・非同期のレプリケーション設計にまとめてあるため、ここでは読み取り側の保証に絞ります。

まとめ|結果整合性で買える可用性と、引き換えに失う読み取りの保証

先に結論を書きます。結果整合性が売っているのは可用性と待機時間で、支払っているのは「読み取りの予測可能性」です。ノードが1台落ちても書き込みを受け付けられる、遠いリージョンからでも数ミリ秒で読める。その対価として、アプリケーションは「今読んだ値が最新とは限らない」という前提でコードを書く義務を負います。この義務を果たさないまま採用すると、原因不明の再現しないバグとして跳ね返ってきます。

設計上の判断は二段構えになります。まずデータ単位で「古い値が見えても後から気づいて直せるか」を判定し、直せないもの——入金記録、在庫の引当、伝票番号の採番——だけは強い整合性で読む。次に、結果整合性のままにした残りへ、自己書き込みの読み取りと単調読み取りをアプリ側で足す。整合性レベルをインスタンス全体で一律に決めるのではなく、読み取り一本ごとに決める。DynamoDBのConsistentReadもCosmos DBのリクエスト単位の上書きも、そのための引数として用意されています。

結果整合性の定義|いつか揃うという保証が及ぶ範囲と及ばない範囲

言葉の定義から始めます。曖昧に使われがちな用語ですが、保証している内容自体はかなり厳密です。

結果整合性の定義|更新が止まれば全レプリカが最後の値へ必ず揃う

正確な言い方はこうなります。あるデータ項目に新たな更新が行われなくなれば、最終的に全てのアクセスがその項目の最後に更新された値を返す。条件節が二つ付いている点に注目してください。「新たな更新が行われなくなれば」と「最終的に」の二つです。

この二つが外れると保証は消えます。更新が秒間何十回と続いているデータについて、結果整合性は何も約束していません。また「最終的」がいつなのかにも上限がない。実装によっては数ミリ秒、分断されていれば数分。上限が欲しければ、後述する有界整合性制約のような別の保証を選ぶことになります。

CAP定理とPACELC|可用性と待機時間のどちらを買う取引か

結果整合性がなぜ生まれたのかは、CAP定理で説明されるのが通例です。ネットワーク分断が起きたとき、整合性と可用性は同時には満たせない。分断中も書き込みを受け付けたいなら、レプリカ間の一致は諦める。ここまでが教科書的な説明。

ただし実務で効いてくるのはPACELC定理のほうです。分断が起きていない平常時にも、整合性(Consistency)と待機時間(Latency)のあいだで選択を迫られる、という拡張になっています。年に数回の分断より、毎リクエスト発生する待機時間のほうが判断材料として重い。東京とバージニアに書き込みを同期させれば往復の物理時間が必ず乗ります。Azure Cosmos DBが5,000マイル(8,000キロメートル)を超えて離れたリージョン構成では強い整合性を既定でブロックしているのも、この物理的な制約を運用ルールに落とした例です。

BASEとACIDの関係|一貫性を後回しにして得る可用性と速度

結果整合性はBASE(Basically Available、Soft state、Eventual consistency)という頭字語の最後の文字として語られます。ACIDの対極に置かれた標語で、「基本的に使える、状態は厳密でない、いずれ揃う」という運用上の性質を並べたもの。

ここで混同が起きやすいので線を引いておきます。ACIDの一貫性(C)は単一ノード内でトランザクションが制約を壊さないことを指し、結果整合性が扱うのはノード間のコピーが一致するかどうか。層が違う話です。単一ノードで版がどう見えるかはMVCCと過去版の可視性の側の主題で、本記事は「その結果が隣のノードへ届くまでのあいだ何が見えるか」だけを扱います。DynamoDBがread-committed分離を提供しつつ既定の読み取りは結果整合性、という組み合わせが成立するのもこのためです。

読み取りがズレる経路|非同期レプリケーションと3つの修復処理

「いつか揃う」の「いつか」を決めているのは、複製の経路と修復の仕組みです。ここを知らないと遅延の見積もりができません。

レプリカ遅延の実体|秒ではなくバイト差で測る遅れの本当の大きさ

非同期レプリケーションでは、書き込みを受けたノードが自分のログへ記録した時点で応答を返し、他のレプリカへの転送はその後ろで走ります。この転送が終わるまでの時間差がレプリカ遅延で、平常時は数ミリ秒から数十ミリ秒。問題は平常時でないときの挙動です。

バッチで大量更新を流した直後、レプリカ側の適用が追いつかず遅延が数十秒へ伸びる。ネットワークが詰まれば分単位にもなる。ここで秒数だけを見ていると判断を誤ります。「3秒遅れ」は積み残しが解消へ向かっているのか増え続けているのかを区別しないからです。積み残しのバイト量を並べれば増加中か減少中かがすぐ分かる。PostgreSQLならLSN差分が対応します。

クォーラムで詰める|W+R>RFが成立するときだけ読めるもの

結果整合性のデータベースの多くは、読み書きそれぞれで何台の応答を待つかを指定させます。Cassandraなら整合性レベルとして ONE・QUORUM・ALL・LOCAL_QUORUM などを選ぶ形。

ここに単純な算術があります。書き込みで応答を待つ台数Wと読み取りで応答を待つ台数Rの合計がレプリカ数RFを上回るとき、読み取り側のレプリカ集合には必ず最新を持つ1台が含まれる。だから W+R>RF が成立していれば、書き込みが後続の読み取りで見えることが保証されます。RF=3でW=QUORUM(2)、R=QUORUM(2)なら4>3で成立。W=ONE、R=ONEなら2>3が偽で成立せず、この構成が最も速く最もズレます。強い整合性か結果整合性かは製品の属性ではなくリクエストごとのパラメータで決まる、という感覚を持てるかが分かれ目です。

3つの修復処理|read repairとヒント再送と定期リペア

ズレたレプリカを揃え直す経路はおおむね3本あります。読み取り時に複数レプリカの値を突き合わせて古い側を書き直すread repair、書き込み先が落ちていたときコーディネータが更新を預かって復帰後に再送するhinted handoff、そして定期的に全データを突き合わせる修復処理です。

Cassandraの公式ドキュメントは、前の2つをbest-effortの技法と位置付け、結果整合性の保証にはそれだけでは足りないと明記しています。だからマークルツリーで不一致箇所を絞り込むanti-entropy repairが用意されている。運用上の含意は一つで、定期リペアを回していない結果整合性クラスタは「いつか揃う」の保証が実質的に切れている状態だということ。ノード復帰後に古い値が残り続ける事故は、ここを止めたまま運用した結果として起きます。

製品ごとの整合性の選び方|DynamoDB・Cosmos DB・Cassandra

保証モデルは共通でも、切り替えの手段と課金への跳ね返りは製品ごとに違います。移行や比較でつまずきやすい対応を先に整理します。

観点 DynamoDB Cosmos DB Cassandra
既定の読み取り 結果整合性 アカウント設定に従う クライアント指定
切り替え単位 読み取り要求ごと 要求ごとに上書き可 クエリごと
中間段階 なし(2択) 5段階 台数指定で連続的
強い側の代償 読み取り単価が2倍 読み取り性能が半分 待機時間と可用性
索引の整合性 GSIは結果整合性のみ コンテナ設定に従う 索引は別管理
複数拠点の既定 結果整合性で複製 非同期で他拠点へ データセンタ単位

DynamoDBの整合性|既定は結果整合性・強い整合性は2倍のRCU

DynamoDBは全ての読み取り操作の既定が結果整合性のある読み込みで、GetItemQueryScanConsistentReadを true で渡したときだけ強い整合性のある読み込みへ切り替わります。コストは倍。結果整合性のある読み込みが強い整合性のある読み込みの半分の単価という関係なので、全読み取りを一律にtrueへ倒すと読み取り課金がそのまま2倍になります。

設計上の制約として押さえるべきは索引の側です。強い整合性のある読み込みが使えるのはテーブルとローカルセカンダリインデックスまでで、グローバルセカンダリインデックス(GSI)とStreamsからの読み取りは常に結果整合性。つまり「GSIで検索して一覧を出す」画面は、どうやっても書き込み直後の反映を保証できません。一覧はGSI、詳細はテーブルへConsistentRead付きで取りに行く、という組み立てが現実解になります。グローバルテーブルも既定はマルチリージョン結果整合性で、他リージョンへの伝搬は通常1秒以内。同期複製が要るならマルチリージョン強整合性を明示的に選びます。

Cosmos DBの5段階|スループットが半分になる強い側の代償

Azure Cosmos DBは強い側から順に、強力・有界整合性制約・セッション・一貫性のあるプレフィックス・最終的の5段階を提供します。2択ではなく段階が刻まれている点が特徴で、なかでもセッションが最も広く使われるレベルとされています。同一クライアントセッション内でなら自分の書き込みが必ず読める、という保証をセッショントークンで実現する仕組みです。

コストの跳ね返り方はDynamoDBと違います。強力と有界整合性制約は4レプリカセット中2レプリカから読む必要があるため、同じ要求ユニット数に対する読み取りスループットが他のレベルの半分になる。単価が上がるのではなく、同じ課金で捌ける量が減る形です。有界整合性制約は遅れの上限をバージョン数Kと時間Tで縛れて、単一リージョンアカウントなら最小10回の書き込みまたは5秒、複数リージョンアカウントなら100,000回の書き込みまたは300秒まで指定できます。製品としての採用判断とRU課金の全体像はCosmos DBの仕組みと採用判断にまとめました。

Cassandraと読み取りレプリカ|整合性をSQLでも選ぶ場面

Cassandraはクエリごとに整合性レベルを指定する方式で、選択肢は ONE・TWO・THREE・QUORUM・ALL・LOCAL_QUORUM・EACH_QUORUM・LOCAL_ONE・ANY。複数データセンタ構成では LOCAL_QUORUM が実務上の落としどころになります。他拠点の応答を待たずにローカルの過半数だけで判定するため、拠点間の往復時間が読み取り待機時間へ乗らない。

同じ判断はリレーショナルデータベースでも発生します。PostgreSQLやMySQLでリードレプリカを立てて参照を逃がした瞬間、その経路は結果整合性になる。SQLで書いているから強い整合性、ではありません。接続先をプライマリにするかレプリカにするかという選択が、そのままCassandraの整合性レベル指定と同じ意味を持ちます。ここが受託開発で最も頻繁に踏まれる地雷です。

アプリ側で塞ぐ整合性の穴|自分の書き込みを必ず読ませる実装手順

データベース側の設定だけでは埋まらない部分があります。利用者から見た「おかしい」の大半は、次の3つをアプリ側へ実装すれば消えます。

自分の書き込みを読む|書き込み直後だけプライマリへ寄せる実装

最も体感に響くのが、登録した直後の画面に自分のデータが出ないという症状です。POSTでレプリカへ書き、リダイレクト先のGETが別のレプリカを読み、まだ届いていない。原因は単純なのに、再現率が低いため調査が長引きます。

解き方は、書き込みを行ったセッションだけ一定時間プライマリへ寄せることです。書き込み時にセッションへ時刻を記録し、そこから数秒間の読み取りだけプライマリへ向ける。全参照を戻す必要はありません。より確実なのは位置情報を持ち回す方式で、Cosmos DBのセッショントークン、PostgreSQLならコミット時のLSNをセッションへ保持し、レプリカがその位置まで追いついているかを見て振り分ける。自分が書いた分だけ待つので、他人の更新の遅れは許容したまま体感の破綻を防げます。

単調読み取りを守る|同じ利用者を同じレプリカへ固定する仕組み

次に多いのが、一度見えた値が次の読み込みで消える症状。リロードのたびに件数が11件と10件を行き来する、といった挙動です。遅れ具合の違うレプリカへ交互に振り分けられると起きます。時間が巻き戻って見えるので、利用者は自分の操作が失敗したと解釈する。

対策は、同じ利用者からの読み取りを同じレプリカへ固定することです。ロードバランサ側でセッションアフィニティを効かせるか、利用者IDのハッシュで振り分け先を決める。これだけで単調読み取り(monotonic reads)が成立し、値が戻る現象は消えます。固定先のレプリカが落ちたときは別へ移りますが、その瞬間だけ巻き戻りが起こり得る点は残る。厳密に潰すなら、前段の位置情報を持ち回す方式と併用します。

冪等性とバージョン|遅れて届いた更新に上書きさせないための設計

3つ目は書き込み側です。結果整合性のシステムでは、リトライや再送で同じ更新が複数回届くことも、古い更新が新しい更新の後から届くことも起こります。何も考えずに最後に届いた値で上書きすると、古い内容へ巻き戻る。

置くべき対策は2つ。更新に単調増加するバージョン番号か更新時刻を持たせ、自分より古い更新は捨てる条件付き書き込みにすること。DynamoDBならConditionExpression、SQLならWHERE version = ? を付けた更新が対応します。もう一つは、書き込み要求へ冪等キーを付けて二重適用を防ぐこと。この2つが入っていれば、再送や順序の入れ替わりが起きてもデータは壊れません。逆に言えば、この2つを入れずに結果整合性のストアへ更新を流す設計は、いつ壊れるかだけが未定の状態です。

結果整合性を選んではいけない業務|金銭と在庫で失うものの実際

ここまでの緩和策を入れてもなお、結果整合性を選んではいけない領域があります。条件で切り分けます。

選んでよい条件|遅れて届いても後から気づいて直せる読み取りだけ

結果整合性で読んでよいのは、古い値が見えたことに後から気づけて、かつ直せる読み取りに限られます。具体的には次の3つ。

  • 閲覧数・いいね数・通知の未読件数(数秒古くても業務判断が変わらない)
  • 商品一覧や検索結果(詳細画面で強い整合性の読み取りを行えば確定できる)
  • 分析ダッシュボードやレポート(そもそも集計時点が過去であることが前提)

共通しているのは、古い値で何かを確定させないという性質です。一覧が数秒古くても、注文の確定処理が最新を読み直すなら実害は出ません。読み取りの目的が「見せる」か「確定させる」かで線を引くと判断が速くなります。

選んではいけない条件|金銭と在庫と採番は強い整合性で読み切る

反対に、条件を問わず強い整合性で読むべき対象もあります。残高と入出金の記録、在庫の引当と払出、伝票番号や会員番号の採番、権限とアクセス制御の判定。共通するのは、古い値で確定処理を通すと不整合が外部へ漏れ出す性質です。

在庫で考えると分かりやすい。残り1個の商品に対して、二人が同時に結果整合性の読み取りで在庫を確認し、両方とも「1個ある」と判断して注文を確定する。売れたのは1個なのに受注は2件。この不整合は自社DB内で完結せず、出荷できない注文と謝罪連絡という形で外へ出ていきます。得られるのは読み取り課金の半減と数ミリ秒の短縮、失うのは受注の正しさ。権限判定も同じ構図で、失効させた権限が古いレプリカに残れば退職者が数分間アクセスできてしまいます。

業務そのものが複数サービスにまたがるなら、強い整合性で読み切るのではなく、業務側で不整合を前提に組む選択肢もあります。処理を段階に分け、失敗した段階を打ち消す取引で戻すSagaパターンと補償トランザクションがその代表です。整合性をデータベース層で買うか業務設計で作るか、という二択だと捉えてください。どちらを選ぶかはデータの性質と組織の運用体制で変わるため、基盤の設計段階から一緒に決めるのが確実です。データベースから分析基盤までを一続きで設計するなら、データ分析基盤構築・MLOps構築支援で受託の相談を受け付けています。

監視に置く指標|遅れの秒数と件数を利用者の体感へ翻訳する方法

結果整合性を採用したなら、遅延は監視対象になります。置く指標は3つ。積み残しのバイト量または件数、遅延の秒数、そして修復処理の失敗回数です。1つ目が増加傾向なら追いつけていない状態で、2つ目だけを見ていても判別できません。

閾値の決め方には工夫が要ります。「遅延3秒で警告」と決めても、それが利用者にとって何を意味するのか分からなければ運用は形骸化する。書き込み直後の再読み取りが起きる典型的な画面遷移の所要時間——登録して一覧へ戻るまでの1.5秒など——を測り、それを超える遅延を「利用者に見える遅れ」として閾値へ置いてください。修復処理の成否も監視対象です。止まった修復処理は、ズレたレプリカをズレたまま残します。

よくある質問

結果整合性の設計で問い合わせの多い5点をまとめます。

結果整合性と強整合性はどちらを既定にすべきですか?

読み取りの用途ごとに決めるのが答えです。製品の既定に合わせるのではなく、確定処理を伴う読み取りだけ強い整合性、表示目的の読み取りは結果整合性という切り分けを行ってください。DynamoDBのように強い整合性のある読み込みが2倍の単価になる製品では、一律に強い側へ倒すと読み取り課金がそのまま倍増します。逆に一律で結果整合性へ倒すと、在庫や残高の確定処理が壊れる。整合性はテーブル単位ではなくクエリ単位の設定だと考えるのが実務的です。

「いつか揃う」の「いつか」はどのくらいの時間ですか?

定義には上限がなく、実装と状況で変わります。平常時の実測でいえば数ミリ秒から1秒程度で、DynamoDBグローバルテーブルのリージョン間伝搬も通常1秒以内とされています。ただしバッチ投入直後やネットワーク障害中は分単位まで伸び得る。時間の上限が業務要件として必要なら、上限を宣言できる保証を選んでください。Azure Cosmos DBの有界整合性制約なら、遅れをバージョン数Kと時間Tで縛れます。

リードレプリカを使うと結果整合性になりますか?

非同期レプリケーションであればそのとおりです。PostgreSQLやMySQLでリードレプリカへ参照を逃がした時点で、その経路の読み取りは結果整合性になります。SQLデータベースだから強い整合性、という理解は誤り。ORMの読み取り専用接続を全参照へ一律に適用すると、登録直後の一覧に自分のデータが表示されない不具合が起きます。書き込み直後の数秒だけプライマリへ寄せる実装を必ず併せて入れてください。

DynamoDBのGSIで強い整合性の読み取りはできますか?

できません。強い整合性のある読み込みが使えるのはテーブルとローカルセカンダリインデックスまでで、グローバルセカンダリインデックスとStreamsからの読み取りは常に結果整合性です。これは設定ではなく仕様上の制約なので、設計側で回避します。一覧や検索はGSIから結果整合性で取得し、確定処理の直前にテーブルへConsistentRead付きで取り直す二段構えが定石になります。

結果整合性のシステムで整合性を検証する方法はありますか?

2つの経路を用意します。1つは定期的な突き合わせで、レプリカ間の差分を検出して修復する処理を回すこと。Cassandraのanti-entropy repairがこれにあたり、マークルツリーで不一致箇所を絞り込みます。もう1つは業務側の突合で、受注と在庫、入金と売掛のように対になるデータの件数と金額を日次で照合する仕組み。前者はデータの一致を、後者は業務の一致を見ています。後者を省くと、不整合の発見が顧客からの申告任せになります。

関連記事

資料請求

RELATED POSTS 関連記事