リードレプリカ
プライマリ DB の読み取り専用コピーで、読み取り負荷を分散しスケーラビリティを向上させる
リードレプリカとは
リードレプリカは、プライマリ DB の読み取り専用コピーで、読み取り負荷を分散しスケーラビリティを向上させる。書き込みはプライマリのみ、読み取りはレプリカに分散する。
可用性のための待機系とは別物である。RDS の Multi-AZ 構成 (別の AZ にスタンバイを 1 台置く形) のスタンバイは読み取りに使えず、読み取り容量を増やしたければリードレプリカを別に足す。読み取りも受けられるのは Multi-AZ DB クラスター構成のリーダーで、こちらは高可用性と読み取り分散を兼ねる。
仕組み
プライマリ DB への書き込みが非同期でリードレプリカにレプリケーションされる。読み取りリクエストをリードレプリカに分散することで、プライマリの負荷を軽減し、読み取りスループットを向上させる。ただし非同期レプリケーションのため、書き込み直後にリードレプリカを読むと古いデータが返る可能性がある (レプリケーション遅延)。
書き込み → プライマリ DB
↓ 非同期レプリケーション
読み取り → リードレプリカ 1
読み取り → リードレプリカ 2
読み取り → リードレプリカ 3
遅延がどこで生まれるかは方式で違う。RDS のリードレプリカはプライマリとは別のインスタンスで、プライマリのトランザクションログを受け取って同じ更新を自分のストレージに再生する。この再生は多くのエンジンで直列に進むため、プライマリの書き込みが増えるほど適用が追いつかず遅延が伸びる。長いトランザクションや一括更新も同じ理由で遅延の山を作る。遅延は CloudWatch の ReplicaLag (Aurora では AuroraReplicaLag) で観測できるので、閾値を決めて監視しておく。
Aurora は同一リージョン内ではレプリカがプライマリと同じクラスタボリュームを共有する。データを送って再生する工程が無いぶん遅延が小さく、AWS は数十ミリ秒程度を典型値として案内している。別リージョンへ延ばす場合、Aurora Global Database の物理レプリケーションでは通常 1 秒未満、バイナリログによる論理レプリケーションでは変更量とネットワークの遅れしだいで伸び得る。
Aurora のリードレプリカ
RDS と Aurora では台数の上限と遅延の桁が違うため、読み取りをどこまでレプリカへ寄せられるかも変わる。
| 観点 | RDS リードレプリカ | Aurora リードレプリカ |
|---|---|---|
| 最大数 | 15 (MySQL / MariaDB / PostgreSQL / SQL Server。Oracle は 5) | 15 |
| レプリケーション遅延 | 書き込み量と再生の進みしだい | 同一リージョンで数十ミリ秒程度 |
| フェイルオーバー | 手動昇格 | 自動フェイルオーバー |
| ストレージ | 独立 | 共有 (クラスタボリューム) |
台数を足しても書き込みが速くならない点は共通である。書き込みが詰まっているならレプリカではなく、インスタンスの拡大かデータの分割で対処する。読み取りが詰まっているなら 1 台足して、遅延の指標と接続先の偏りを合わせて見る。
DynamoDB のリードレプリカ
DynamoDB はリージョン内で自動的に 3 つの AZ へデータを複製する。台数や配置を指定する余地は無く、こちらで選べるのは読み取りごとの整合性だけである。
// 結果整合性 (デフォルト): どの複製から返るかは決まっていない (速く、安い)
await db.get({ TableName: 'users', Key: { id: '123' } });
// 強い整合性: 直前の書き込みまで反映された値が返る (遅く、高い)
await db.get({ TableName: 'users', Key: { id: '123' }, ConsistentRead: true });
強い整合性の読み取りには制約が 3 つある。4 KB までの項目で消費するのは 1 読み取り単位で、結果整合性の 0.5 単位に対して 2 倍かかる。グローバルセカンダリインデックスに対しては指定できない。レイテンシも結果整合性より上がる。既定を強い整合性へ寄せると費用と応答時間の両方に効くため、必要な読み取りにだけ付ける。
リードレプリカの注意点
つまずくのは遅延そのものより、遅延がある前提で書かれていないコードである。
| 注意点 | 対策 |
|---|---|
| 書き込み直後の読み取りで古い値が返る | その読み取りだけプライマリへ向ける (次節の Read Your Own Writes) |
| 遅延が伸びても気づけない | 遅延の指標を監視し、閾値を超えたら読み取りをプライマリへ寄せる |
| 昇格は自動では起きない | RDS のリードレプリカ昇格は手動操作。切り替え手順と接続先の変更方法を先に用意する |
| 台数を増やしても書き込みは速くならない | 書き込みが上限ならインスタンスの拡大かデータの分割で対処する |
Read Your Own Writes
自分が書いた値だけは必ず自分に見えるようにする、という線引きである。すべての読み取りを強い整合性にすると費用と応答時間を捨てることになるので、書き込み直後の 1 回だけを強い整合性にする。
// 書き込み直後はプライマリから読み取り
await db.put({ TableName: 'users', Item: updatedUser });
// 直後の読み取り: 強い整合性
const user = await db.get({
TableName: 'users',
Key: { id: updatedUser.id },
ConsistentRead: true,
});
// それ以外の読み取り: 結果整合性 (デフォルト)
SQL 系でも考え方は同じで、書き込みを行ったセッションだけを一定時間プライマリへ固定するか、更新した行の識別子を持ち回って該当の読み取りだけプライマリへ回す。利用者ごとに「直前に書いたか」を持てば、影響を受けるのはその利用者の数回の読み取りだけで済む。
リードレプリカ vs キャッシュ
どちらも読み取りを軽くする道具だが、効く相手が違う。
| 観点 | リードレプリカ | キャッシュ (DAX, ElastiCache) |
|---|---|---|
| データの鮮度 | 数ミリ秒〜数秒遅れ | TTL に依存 |
| 一貫性 | 結果整合性 | キャッシュミス時に DB から取得 |
| コスト | DB インスタンス費用 | キャッシュノード費用 |
| 用途 | 読み取り負荷の分散 | 低レイテンシの読み取り |
選び分けの目安は、読み取りが同じキーに集中しているかどうかである。集中しているならキャッシュが効き、多様なクエリが広く来るならレプリカのほうが素直に効く。DynamoDB の DAX には注意点があり、結果整合性の読み取りはキャッシュから返るが、強い整合性を指定した読み取りは DAX を素通りして DynamoDB へ行き、結果もキャッシュされない。強い整合性が既定になっている経路をそのまま DAX に載せても、キャッシュヒットは増えない。
この記事は役に立ちましたか?
関連用語
Aurora
AWS のクラウドネイティブ RDB で、MySQL/PostgreSQL 互換で高可用性と高パフォーマンスを実現する
結果整合性
分散システムで更新が全ノードに即座に反映されず、最終的に一貫した状態に収束するモデル
水平スケーリング
サーバーの台数を増やして処理能力を向上させるスケーリング手法
CQRS
データの読み取り (Query) と書き込み (Command) を別々のモデルで処理し、それぞれを独立して最適化するアーキテクチャパターン
NoSQL
リレーショナルモデル以外のデータベースの総称で、スケーラビリティと柔軟性を重視する
変更データキャプチャ (CDC) とは - DB の変更をリアルタイム連携するパターン
変更データキャプチャ (CDC、Change Data Capture) はデータベースの INSERT/UPDATE/DELETE を検出して検索エンジンや分析基盤へリアルタイムに伝播させるデータ統合パターン。実装 4 方式と AWS での構成を解説
関連する記事
チーム開発 / マネジメント本ガイド - 技術リーダーが読むべき本
チーム開発、1on1、技術マネジメントを学べる技術書の選び方を紹介。メンバー時代からマネージャーまで、段階別の読書ロードマップを解説します。
障害対応の夜に思い出す、あの本の 1 ページ
本番障害の緊迫した場面で、過去に読んだ技術書の知識が助けてくれた経験はありませんか。「いつか役立つ」知識が「今この瞬間」に変わる読書の価値を考えます。
OS / 低レイヤー本ガイド - コンピュータの仕組みを学ぶ技術書の選び方
OS、コンパイラ、ネットワークなど低レイヤーを学べる技術書の 4 ジャンルと、どこから始めるべきかの指針、賞味期限の見極め方を紹介します。