こんにちは。ソフトブレーン開発 保守Tの小松です。
本日はAmazon Auroraデータベースについてのお話をしたいと思います。
Amazon AuroraデータベースはAWSが提供するフルマネージドサービス型のRDBMSになり、
MySQL互換と、PostgreSQL互換のものがあります。
Auroraの特徴としては、単純に標準のMySQL/PostgreSQLと比較して早いということが謳われていますが、それ以外にも以下の機能があります。
・データをレプリケーションでき、障害発生時に自動的にレプリカにフェイルオーバーできる
・リード用のクエリをレプリカへ投げることで、負荷を分散させることができる
・負荷に合わせて、レプリカを自動的に追加(オートスケール)することができる
これらの機能を使うことで、データベースの可用性を高めることができます。
Auroraデータベースの作成方法は割愛しますが、AWSコンソールでAuroraのクラスタを作成すると、クラスタのエンドポイントと、読み込み用(レプリカ)のエンドポイントが発行されます。アプリケーションにてこれらに接続することでAuroraを利用することができます。
ただし、エンドポイントが2つあるので、アプリケーション側ではどちらのエンドポイントを使うか制御しなくてはなりません。
ここからはPostgreSQL互換限定のお話となってしまいますが、アプリケーション側で制御する処理を実装することなく、レプリカへの負荷分散を実現する方法としては、アプリケーションとAurora(PostgreSQL)の間にPgpoolというミドルウェアを挟む方法があります。
https://www.pgpool.net/docs/latest/ja/html/index.html
PgpoolはPostgreSQLとクライアントアプリケーションの間に入るプロキシソフトで、名前の通りコネクションプーリング機能を持たせるために使うこともできますが、負荷分散のための機能も持っています。
Aurora(PostgreSQL)でも利用することができ、Pgpoolにクラスタと読み込み用の2つのエンドポイントを設定しておくことで、SELECTクエリを読み込み用のエンドポイントに実行してくれるようになります。
なお、同一トランザクション内で書き込みが発生した場合、トランザクション終了までSELECTクエリはクラスタエンドポイントに投げ続けるようになります。
1点注意点として、書き込み時にレプリカへの反映には数百ミリ程度のタイムラグが発生することがあります。そのため、例えばWebアプリケーションで1リクエストの処理中に複数のトランザクションが発生する場合、コミットしたデータを別トランザクションですぐに取得しようとすると、レプリカに反映が間に合わず、登録/更新前のデータを取得してしまって、アプリケーションが想定外の挙動を取ることがあります。
この問題の対策としてトランザクション自体の見直しが考えられますが、簡単に対応したければ、SELECTクエリにコメントを付けることで、クエリの投げ先をクラスタエンドポイントに固定することができます。
https://www.pgpool.net/docs/latest/ja/html/runtime-config-load-balancing.html
レプリカへの反映ラグによるアプリケーションの不具合は、開発時点では中々気づけないので注意して頂ければと思います。