概要
Read Replica とは、**「メインDBの読み取り専用コピー」**のこと。
なぜ必要なのか
アプリが成長してユーザーが増えると、1台のDBにアクセスが集中してパンクする。
ユーザー100人
→ SELECT が毎秒1000回
→ INSERT/UPDATE も毎秒100回
→ 1台のDBに全部集中 → パンク
DBへのアクセスは一般的に 「読み取り(SELECT)が8〜9割、書き込みが1〜2割」。 Read Replica は「読み取りだけ別のサーバーに分散させる」という発想で生まれた。
仕組み
アプリ
├─ 書き込み系 ──→ 【Primary DB】(マスター)
│ ↓ binlogをリアルタイム転送
└─ 読み取り系 ──→ 【Read Replica】(スレーブ)
PrimaryのbinlogをRead Replicaに転送・適用し続けることで、常に最新のデータが同期される。
Primary と Read Replica の役割分担
| 操作 | どちらに送る? |
|---|---|
| INSERT / UPDATE / DELETE | Primary のみ |
| SELECT(重いレポート系クエリ) | Read Replica |
| SELECT(一覧表示など) | Read Replica |
| トランザクションを伴う処理 | Primary のみ |
Railsでの実装
Rails 6以降は 複数DB接続 が標準サポートされている。
# config/database.yml
production:
primary:
adapter: mysql2
host: primary.rds.amazonaws.com
# 書き込み用
primary_replica:
adapter: mysql2
host: replica.rds.amazonaws.com
replica: true # これを付けるだけで読み取り専用に
# モデルで接続先を切り替える
class ApplicationRecord < ActiveRecord::Base
connects_to database: {
writing: :primary,
reading: :primary_replica
}
end
# コントローラなどで明示的に切り替える
ActiveRecord::Base.connected_to(role: :reading) do
# このブロック内のSELECTはすべてReplicaへ
@items = Item.where(status: "active").limit(20)
end
重要な注意点:レプリケーションラグ
Read Replica には 「レプリケーションラグ」 という避けられない特性がある。
Primary に INSERT
↓ binlog転送(数ms〜数百ms)
Read Replica に反映
この「数ms〜数百ms」の間に Read Replica を参照すると
古いデータが返ってくることがある
ラグが問題になる具体例
① ユーザーが会員登録(INSERT → Primary)
② すぐに一覧ページをリロード(SELECT → Replica)
③ まだ同期されていないので自分が表示されない
対策パターン
# 書き込み直後は必ずPrimaryから読む
def create
@user = User.create!(user_params)
# リダイレクト先でも書き込みロールで読む
redirect_to user_path(@user)
end
# または書き込み後の一定時間はPrimaryへ誘導する仕組みを入れる
AWS RDSでのRead Replica
RDS Primary(Multi-AZ)
├─ 同一リージョンのRead Replica → 低レイテンシ・負荷分散
└─ 別リージョンのRead Replica → 災害対策(DR)
- コンソールやTerraformから数クリックで追加できる
- Read ReplicaをそのままPrimaryに昇格させることもできる(フェイルオーバー)
- Replicaだけインスタンスタイプを落としてコスト削減も可能
まとめ
| 項目 | 内容 |
|---|---|
| 何のため? | 読み取り負荷の分散、パフォーマンス向上 |
| 仕組みは? | binlogをPrimaryからReplicaに転送・適用 |
| 書き込みは? | Primaryのみ(Replicaは読み取り専用) |
| 注意点は? | レプリケーションラグがある |
| Railsでは? | connects_to で接続先を役割ごとに定義できる |