はじめる前に
- 必須AWS アカウントを持っていること
- 必須マネジメントコンソールにサインインできること
- 必須RDS で DB インスタンスを作成した経験があること
- 必須基本的な SQL の実行経験があること(
INSERT、SELECT) - あると良い「読み取りと書き込みでアクセスが多い方を分散する」という考え方のイメージ
※ コンソール操作に加えて、ローカルのターミナルから mysql クライアントで SQL を実行します。RDS をパブリックアクセス可能にして、ローカルから直接接続します。
参照する公式ドキュメント
手順に迷ったときや、用語の意味を確かめたいときに開きましょう。
※ リンク切れの場合は、ページタイトルで検索してください。
背景・シナリオ
アプリケーションが大きくなると、データの読み取り(SELECT)が書き込みより圧倒的に多くなる場面が出てきます。1 台のデータベースに全部のアクセスを集中させると、読み取りの負荷が書き込みの性能にも影響してしまいます。
RDS のリードレプリカは、元のデータベース(プライマリ)の複製を読み取り専用として用意し、読み取りのアクセスを分散できる仕組みです。今回は実際にプライマリとリードレプリカを 1 つずつ作成し、書き込みと読み取りの役割が分かれていく様子を手元で確認します。
リードレプリカに直接書き込みはできるの?
できません。リードレプリカは読み取り専用です。書き込みは必ずプライマリに対して行い、その内容が非同期でレプリカに反映される、という一方向の関係です。
書き込んだ内容は、レプリカにすぐ反映されるの?
必ずしも即時ではありません。プライマリとレプリカの間にはわずかな時間差(レプリケーションラグ)が生じます。「最新の状態を必ず読む必要がある処理」をレプリカに任せると、古い内容を読んでしまう可能性がある点に注意が必要です。
RDS for MySQL のプライマリインスタンスを作成し、そこからリードレプリカを 1 つ作成する。プライマリに書き込んだデータが、少し時間をおいてレプリカ側でも読み取れるようになることを実際に確認する。
つくる構成
プライマリインスタンスとリードレプリカを 1 台ずつ用意します。書き込みはすべてプライマリへ、読み取りはどちらにも行えますが、今回はレプリカ側で読み取りを確認します。複製は非同期で行われます。
要件
以下の要件を満たす構成を作り、プライマリとリードレプリカの分担を確認してください。
| No | 要件 |
|---|---|
| 1 | リージョンは「東京(ap-northeast-1)」を使用する。 |
| 2 | RDS for MySQL のプライマリインスタンスを 1 つ作成する(パブリックアクセス「あり」、セキュリティグループのインバウンドはマイ IP のみ許可)。 |
| 3 | プライマリのデータベースにテーブルを 1 つ作成し、データを数件 INSERT する。 |
| 4 | プライマリインスタンスからリードレプリカを 1 つ作成する(リージョン・アベイラビリティーゾーンは自由に選んでよい)。 |
| 5 | リードレプリカに接続し、プライマリで追加したデータが SELECT で取得できることを確認する。さらにプライマリへ追加のデータを INSERT し、少し待ってからレプリカ側で同じデータが見えるようになることを確認する。 |
構築の進め方
「プライマリを作る → データを書き込む → レプリカを作る → 反映を確認する」という順番で進みます。
-
マネジメントコンソールにサインインし、リージョンを合わせる
ブラウザで AWS マネジメントコンソールにサインインし、画面右上のリージョンが「アジアパシフィック(東京)ap-northeast-1」になっていることを確認します。
-
RDS でプライマリインスタンスを作成する
RDS コンソールの「データベースの作成」から、エンジンの種類で「MySQL」を選びます。インスタンス識別子は自由に決めます(例:
primary-db)。次の点に注意して設定します。パブリックアクセス あり VPC セキュリティグループ 新規作成し、インバウンドで MySQL/Aurora(3306)をマイ IP のみから許可 マスターユーザー認証情報 ユーザー名・パスワードを自由に決める(後で接続に使うため記録しておく) インスタンスサイズ 無料利用枠の対象、または小さめのクラス(例: db.t3.micro)なぜパブリックアクセスを「あり」にするの?今回はローカルのターミナルから直接 SQL を実行して動作を確認するため、パブリックアクセスを有効にしています。インバウンドをマイ IP のみに絞ることで、自分の環境からしか接続できない状態を保ちます。
-
プライマリへ接続し、テーブルとデータを用意する
インスタンスが「利用可能」になったら、詳細画面のエンドポイントを確認します。ローカルのターミナルから
mysqlクライアントで接続し、データベース・テーブルを 1 つ作成して、データを 2〜3 件INSERTします。# プライマリのエンドポイントへ接続 mysql -h primary-db.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -u 設定したユーザー名 -p -- 接続後、データベースとテーブルを作成 CREATE DATABASE shopdb; USE shopdb; CREATE TABLE items (id INT PRIMARY KEY, name VARCHAR(50)); INSERT INTO items VALUES (1, 'apple'), (2, 'banana'); SELECT * FROM items;
テーブル名・カラムは自由上記は一例です。テーブル名やカラム構成は自由に決めて構いません。あとでレプリカ側から同じ内容が見えることを確認するので、内容を覚えておきましょう。
-
プライマリインスタンスからリードレプリカを作成する
RDS コンソールでプライマリインスタンスを選び、「アクション」→「読み取りレプリカの作成」を行います。リージョンやアベイラビリティーゾーンは自由に選んでよいですが、セキュリティグループとパブリックアクセスの設定はプライマリと同様にします(パブリックアクセス「あり」、マイ IP のみ許可)。
レプリカ識別子も自由に決める例:
read-replica-db。プライマリと区別しやすい名前にしておくと、あとの手順が分かりやすくなります。 -
リードレプリカの作成完了を待つ
RDS コンソールの「データベース」一覧で、ステータスが「利用可能」になるまで待ちます。作成にはしばらく時間がかかります。
-
リードレプリカへ接続し、データが見えることを確認する
リードレプリカの詳細画面でエンドポイントを確認し、
mysqlクライアントから接続します。手順 3 で作成したテーブルとデータが、そのまま見えることを確認します。# リードレプリカのエンドポイントへ接続 mysql -h read-replica-db.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -u 設定したユーザー名 -p -- 接続後、プライマリで作成した内容が見えるか確認 USE shopdb; SELECT * FROM items;
-
プライマリに追加のデータを書き込む
プライマリのエンドポイントへ再度接続し、追加のデータを
INSERTします。INSERT INTO items VALUES (3, 'cherry'); SELECT * FROM items;
-
リードレプリカ側で反映を確認する
リードレプリカへ接続したまま(または再接続して)、同じテーブルを数回
SELECTします。追加したデータが、時間差を伴って反映されることを確認します。-- 反映されていなければ少し待って再実行する SELECT * FROM items;すぐ反映されないこともある反映までの時間はそのときの状況によって変わります。すぐに見えなくても焦らず、数十秒〜数分待ってから再実行してみましょう。
つまずきポイント
初学者がよく引っかかる箇所を先回りでまとめました。答えそのものは載せていませんが、「どこを見直せばよいか」の手がかりとして使ってください。
「INSERT を実行したら、読み取り専用だというエラーが出た」
リードレプリカは読み取り専用であり、書き込み操作(INSERT / UPDATE / DELETE)は受け付けない、という仕様によるものです。書き込みが必要な操作は、必ずプライマリのエンドポイントに対して行っているかを見直しましょう。
「SELECT しても、追加したはずのデータが出てこない」
プライマリとレプリカの間にはレプリケーションラグにより多少の時間差が生じることがあります。気長に少し待ってから再実行して確認しましょう。接続先のエンドポイントを取り違えていないかも、あわせて見直すとよいでしょう。
完了チェック
要件の再確認ではなく、画面のどこを見れば達成を確認できるかをまとめました。RDS コンソールとターミナルを開いて、次を順に確かめましょう。
- リードレプリカのステータスが「利用可能」になっている。
- リードレプリカの「ロール」または詳細画面で、プライマリとの関係(レプリケーション元)が確認できる。
- プライマリで作成したテーブルが、リードレプリカ側でも同じ内容で見える。
- プライマリへの追加データが、リードレプリカ側でも(時間差を伴って)見える。
- リードレプリカへの書き込みを試すと、読み取り専用であることを示すエラーになることを確認できる。
考えてみよう
手を動かすことに加えて、次の問いに自分の言葉で答えられるようにしておくと、理解がより深まります。
- レプリケーションラグがある状態で、「商品の在庫数を確認してすぐ購入確定する」処理をレプリカに任せると、どんな問題が起こりうるでしょうか。
ヒント
レプリカが読み取る内容は、プライマリより少し古い可能性があります。在庫数のように「最新であることが重要」な値を古い状態で読んでしまうと、実際には売り切れているのに購入できてしまう、といった不整合が起こり得ます。 - リードレプリカを複数台作ったら、読み取りの負荷はどう変わりそうでしょうか。
ヒント
読み取りのアクセスを複数のレプリカに振り分けられれば、1 台あたりの負荷は下がります。一方で、複製元であるプライマリへの書き込み負荷や、複製にかかる処理は台数が増えても変わらない点も合わせて考えてみましょう。 - プライマリに障害が起きた場合、リードレプリカは自動的にプライマリの代わりになるでしょうか。
ヒント
リードレプリカは「読み取りの負荷分散」が目的の仕組みであり、障害時に自動でプライマリの役割を引き継ぐ「フェイルオーバー」とは異なる機能です。可用性を高める目的の仕組みと、負荷分散を目的とした仕組みの役割の違いを区別して考えてみましょう。
後片づけ
削除の順番が大事です。リードレプリカを先に削除し、そのあとプライマリインスタンスを削除します。
- リードレプリカを削除する:RDS コンソールの「データベース」一覧からリードレプリカを選び、削除します。
- プライマリインスタンスを削除する:同様にプライマリインスタンスを選び、削除します。削除時に「最終スナップショットを作成するか」を選択できます。検証用であれば作成しない選択でも構いませんが、内容を残したい場合は作成を選びましょう。
- セキュリティグループを削除する:上記 2 つの削除が完了したあと、作成したセキュリティグループを削除します。
レプリカを先に削除し、他のリソースを間違えて消さない
プライマリを先に削除しようとすると、関連するリードレプリカが残っている場合に進められないことがあります。必ずリードレプリカ→プライマリの順で削除しましょう。また、セキュリティグループやデフォルト VPC など、このハンズオン以外で使っているリソースを間違えて削除しないよう、名前を確認してから操作してください。
コストに関する注意: リードレプリカはプライマリと同様にインスタンス時間に応じた料金が発生します。実質、稼働時間中は2 台分の DB インスタンス料金が課金される状態になります。あわせて、各インスタンスのストレージ(割り当てたストレージ容量)にも料金がかかります。VPC・セキュリティグループ自体には料金はかかりません。検証が終わったら、上の「後片づけ」の手順でプライマリ・リードレプリカの両方を削除することを忘れないようにしましょう。最新の料金は AWS の公式料金ページで確認してください。