株式会社ジオデータ開発 ロゴ
株式会社ジオデータ開発GEO DATA DEVELOPMENT Inc.

DATABASE / DISTRIBUTED SYSTEMS

分散データベース入門シャーディング・レプリケーション・2相コミットを図解で理解する

ネットショップで「注文が確定しました」と表示されたのに、別の画面には古い在庫数が残っている。複数のデータベースにまたがる更新が、片方だけ成功した。データを分散させると便利になる一方、こうした問題が生まれます。分散配置・複製・トランザクションを順番に理解しましょう。

分散データベースシャーディングパーティショニングレプリケーション非同期レプリケーション同期レプリケーションレプリカ遅延フェイルオーバー

011台のデータベースでは何が困る?

小さなネットショップなら、商品・在庫・注文・会員を1台のデータベースで管理できます。ところが利用者が増えると、読み書きが集中し、バックアップや障害復旧にも負担がかかります。1台の故障でサービス全体が止まる構成も不安です。

そこでデータを複数のサーバーで扱う「分散データベース」を検討します。分散とは単にサーバーを増やすことではなく、どのデータをどこに置くか、更新をどう伝えるか、故障時に何を保証するかを決める設計です。

02分散データベースの全体像

技術解決したい問題大まかな仕組み
シャーディングデータ量・書き込み負荷を分散注文IDや顧客IDで保存先を分ける
レプリケーション読み取り負荷分散・冗長化同じデータのコピーを別ノードに保持
分散トランザクション別ノードの更新結果の不一致を防ぐ複数の更新を一括成功・失敗として調停

これらは排他的な技術ではありません。各シャードをさらに複製する構成も一般的です。一方で、複製先が増えたからといって複数シャードの更新が自動的に原子的になるわけではありません。

03シャーディング:データを分けて持つ

シャーディング(Sharding)は、例えば顧客IDのハッシュ値などに応じて、データを異なるサーバーへ振り分ける方法です。注文100万件を3台で分担すれば、1台ですべてを保持する必要がなくなります。図ではわかりやすく注文IDの範囲で区切っています。

データを分担するシャーディング
注文データを振り分け注文ID → 保存先を決定シャード 1注文ID 101〜199シャード 2注文ID 200〜299シャード 3注文ID 300〜399各シャードは異なるデータ範囲を担当

分割キーの選び方は重要です。特定の人気商品や大型顧客だけにアクセスが集中すると、そのシャードだけが忙しくなる「ホットスポット」が発生します。複数シャードにまたがる集計や結合も複雑です。

04レプリケーション:同じデータを複製する

レプリケーション(Replication)は、プライマリの更新内容をレプリカへ伝え、同じデータを複数ノードに保持する仕組みです。読み取りをレプリカへ分散したり、プライマリ障害時の切替先を用意したりできます。

同じデータを複製するレプリケーション
プライマリDB注文 #101 を更新読み書き元更新済み #101レプリカ 1#101 を複製レプリカ 2#101 を複製複製の反映時刻は方式や通信状況によって異なる

代表的な構成では、書き込みをプライマリが受け、WAL(Write-Ahead Log)などの変更記録をレプリカへ転送して反映します。実装により物理・論理レプリケーションなどがあります。重要なのは複製が「いつ完了した」と扱われるかです。

05非同期レプリケーションの流れと落とし穴

非同期レプリケーションでは、プライマリがローカルの確定条件を満たすと、レプリカの反映完了を待たずに利用者へ成功を返せます。そのため書き込み応答を比較的速くしやすい一方、プライマリとレプリカの間に短い差が生まれます。

STEP 1

プライマリに書き込む

商品在庫を10個から9個に変更し、プライマリでCOMMIT。

STEP 2

先に成功を返す

レプリカの更新を待たずに『注文完了』を返す。

STEP 3

あとから反映

変更ログが転送され、レプリカの在庫数も9個になる。

転送前にレプリカを読むと、まだ10個と表示されることがあります。これがレプリカ遅延(Replication Lag)です。さらに、プライマリが停止し、まだ変更を受け取っていないレプリカを昇格させると、利用者には成功と返した直近の更新が失われる可能性があります。

06同期レプリケーションとの違い

同期レプリケーションは、設定されたレプリカから所定の確認応答が返るまで書き込み完了の応答を待つ方式です。たとえば「レプリカがWALを永続化した」ことを確定条件にすれば、プライマリ単独障害時のデータ損失リスクを下げられます。ただし通信往復やレプリカの状態が書き込み待ち時間に影響します。

比較非同期レプリケーション同期レプリケーション
書き込み応答レプリカの完了を待たずに返せる指定したレプリカの確認を待つ
遅延通常は抑えやすいネットワーク往復の影響を受ける
切替時の損失未転送分を失う可能性確認済み範囲の耐久性を高められる
レプリカ障害基本的に書き込みを継続しやすい必要な応答を得られず待機する場合がある
用途読み取り分散、多少の遅延を許容確定済み更新の耐久性を重視

なお「同期」といっても、転送済み・ディスクへ永続化済み・問い合わせから参照可能、のどこまで待つかで保証が変わります。PostgreSQLの remote_write、on、remote_apply などがその例です。

07障害とフェイルオーバー

プライマリが故障し、レプリカを新しいプライマリとして昇格させる処理をフェイルオーバーといいます。ただし切り替えるだけでは安全とは限りません。旧プライマリが復帰して両方が書き込みを受ける「スプリットブレイン」を避けるため、リーダー選出やフェンシング(旧リーダーの書き込み禁止)などが必要です。

障害例起こり得る問題設計上の対策
非同期転送の遅れ昇格先に最新のデータがない遅延監視、許容損失量の定義
プライマリ停止書き込み停止・切替待ち監視、昇格判断、切替手順
ネットワーク分断複数ノードが自分を主系と判断適切なリーダー選出、フェンシング
古いレプリカへの読み取り直前の変更が見えない重要な読み取りは主系へ、整合性要件に応じた読取制御

08整合性・可用性・通信遅延を考える

「同じデータを複数台に持つ」だけで、どのサーバーから読んでも常に同じ値になるわけではありません。非同期複製では時間の経過とともに値が収束する結果整合性(Eventual Consistency)が典型的な選択肢です。ただしアプリケーションは、更新直後に自分の更新が見えることを要求する場合があります。

一方で、異なるノードを含む取引の原子性、読み取りの新鮮さ、サービスが応答できることは、それぞれ別の保証です。ネットワーク分断時は整合性と可用性の両立に制約が生じますが、CAP定理だけで具体的なDBの挙動を丸ごと説明することはできません。どの操作に何を保証するのかを確認する必要があります。

09複数DBをまたぐ注文処理の難しさ

ECサイトの注文を考えます。注文DBに「注文済み」と記録し、別の在庫DBから1個減らす必要があるとします。2台をそれぞれ独立にCOMMITすると、最初のDBだけ成功して次で障害が起きるかもしれません。

STEP 1

注文DB

注文 #101 を『確定』で登録する。

STEP 2

在庫DB

在庫10個から9個に減らす。

STEP 3

途中で障害

注文だけ確定して在庫が残ると業務上の不整合が発生。

単一のリレーショナルDB内であれば通常は1つのローカルトランザクションでまとめられます。しかし独立したDBやシャードをまたいで、全体でAll or Nothing(全部成功または全部中止)を必要とするなら、分散トランザクションの調停が課題になります。

102相コミット:全体の確定をそろえる

2相コミット(Two-Phase Commit、2PC)は、調停者(Coordinator)が各参加者(Participant)へ確認を取り、全参加者のトランザクションをまとめてCOMMITまたはABORTするための手順です。

段階調停者参加者
第1相:Prepare(準備・投票)各DBに『確定できるか』問い合わせる更新を準備・必要なログを永続化し、YES/NOを返す
第2相:Commit / Abort(最終決定)全員YESならCOMMIT、それ以外は原則ABORTを決め、記録して通知通知に従って確定または中止し、完了を返す
調停者注文DB在庫DBPreparePrepareYESYESCOMMITCOMMITACKACK参加者は準備済み・最終決定待ち調停者が決定を記録

「YES」はCOMMIT済みではありません。「最終決定が来ればCOMMITできる」という準備完了の約束です。全員YESでも決定通知を待つ必要があります。

11調停者が止まるとどうなる?

注文DBと在庫DBがYESを返した直後、調停者が停止したとします。どちらのDBも、全体でCOMMITするのかABORTするのかをまだ知らない可能性があります。自分で勝手にCOMMITやROLLBACKを選ぶと、別の参加者の結果と食い違う危険があります。

このためPrepared状態で待ち続けることがあり、ロックやリソースが保持されて後続処理を妨げます。これを2PCのブロッキング問題と呼びます。調停者の決定ログや参加者の状態を確認し、定められた復旧手順に従う必要があります。

12レプリケーションと2PCは別の問題を解く

方式主に何をそろえる?いつ待つ?注意点
非同期レプリケーション同じデータのコピー複製完了を通常は待たない遅延、古い読み取り、未複製分の損失
同期レプリケーションコピーの所定の受信・永続化等指定レプリカからのACKまで待ち時間、レプリカ不調による停止
2相コミット別々の更新参加者の確定/中止準備票と最終決定を調停Prepared中のブロッキング、復旧管理

シャーディングは配置、レプリケーションは複製、2PCは更新の原子性を扱います。3つを同時に利用することもあれば、どれかだけを利用することもあります。

したがって「レプリケーションが非同期で、2PCが同期」と単純に二分するのは正確ではありません。非同期/同期という区分はレプリケーション自身にもあり、2PCの「2相」はPrepareとCommit/Abortという決定手順を指します。

13Saga・Outbox・単一DBの選択肢

2PCを採用すれば、すべての設計が楽になるわけではありません。参加者全員が準備・確定手順に対応し、障害時に未解決のPreparedトランザクションを復旧できることが必要です。外部決済やメール配信など、すでに起きた現実の操作は厳密にROLLBACKできないこともあります。

選択肢考え方向いている場面・注意
単一DBトランザクション更新を1つのトランザクション境界に収める最も単純な候補。要件次第では分散不要
2PC全参加者のCOMMIT/ABORTを調停厳密な一括確定が必要。長い待機やロックに注意
Sagaローカル確定をつなぎ失敗時に補償業務的な取り消しを設計できる。瞬間的な不整合はあり得る
Transactional Outbox業務更新と送信予定イベントを同一DBで確定イベント送信の取りこぼしを抑える。受信側の冪等性も必要

例えば注文確定後にメールを送る処理まで2PCに含めるのは通常難しいため、Outboxと再送・重複排除の方が適切なことがあります。方式は厳密な同時確定が必要か、後から収束・補償できるかで選びます。

14操作ラボで違いを体験する

同じ「注文を確定する」という場面でも、複製を待つか・故障が起こるか・複数DBがYESを返すかで結果が変わります。まずレプリケーションの遅延と切替、次に2PCの投票とブロッキングを動かしてみてください。実DBへは接続しない概念シミュレーターです。

LAB 01 / REPLICATION

同じ注文を非同期・同期で処理してみる

注文を行い、レプリカへ変更を届ける前後の在庫数を見比べます。同期モードは「レプリカが反映したことを待つ」簡略モデルです。実製品では受信・永続化・適用のどこまで待つかは設定によって違います。

PRIMARY

プライマリDB

10個

書き込み元

REPLICA

レプリカDB

10個

ここまでの更新が反映されています

現在の状態: 注文前:プライマリもレプリカも在庫10個です。

概念モデル上、在庫更新を仮置きして同期の待機を示しています。実DBではWALの永続化・待機中のトランザクション状態などがあり、このUIの数値表示と完全には一致しません。障害後の自動フェイルオーバーも実行しません。

LAB 02 / DISTRIBUTED TRANSACTION

2相コミットの準備・確定を追う

今度はレプリカではなく、別々の情報を持つ「注文DB」と「在庫DB」の両方を更新します。障害タイミングと在庫DBの応答を選んで、1段階ずつ進めてください。

1開始
2Prepareを要求
3YES / NO の投票
4最終決定を通知
5終了
STEP 1

調停者が注文DBと在庫DBにまたがる取引を開始します。

理解チェック

注文DBと在庫DBがYESを返したあと調停者が停止した場合、参加者が取るべき行動は?

15実務での設計チェック

確認事項具体的な問い
分割キー顧客・注文・商品、何を基準にシャードを切る?
読み取りの新鮮さ更新直後はプライマリを読む必要がある?
複製の耐久性何件・何秒分の未複製データ損失を許容できる?
切替の安全性旧リーダーを確実に書き込み禁止にできる?
トランザクション境界複数DBの厳密な原子性が本当に必要?
未解決2PCの復旧決定ログ、Prepared状態、ロック待ちを監視できる?
代替案単一DB、Saga、Outboxで要件を満たせない?

DBの製品ごとに、複製の確認条件、リーダー選出、分散トランザクションの対応範囲は異なります。アーキテクチャ図だけでは保証は分からないため、公式仕様と障害試験で確かめます。

16まとめ

分散データベースの理解は、「データをどこに置くか」「コピーをいつそろえるか」「異なる更新をどう確定するか」の3つに分けると整理できます。シャーディングは分割、レプリケーションは複製、2相コミットは分散した更新の原子性を調停します。

非同期レプリケーションは応答を速くしやすい一方でレプリカ遅延や切替時の損失が課題です。同期レプリケーションは複製先の確認を待ちますが、その分遅延や停止の影響を受けます。2PCは全参加者の確定をそろえますが、Prepared後の障害で待機が長引く可能性があります。

参考資料