読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

「FuelPHP」で「リードレプリカ」を使ってみる

サーバ担当の中村です。

今回は「FuelPHP」でAWSのRDSの機能の「リードレプリカ」を使う方法について書いてみようと思います。

【そもそもリードレプリカとは何か?】

読んでその名の通り、「リード(参照)するためのレプリカ(模造品)」です。 最近、「大規模システムにおいてビッグデータをどう扱うか」ということが話題に上ることがよくあります。 DBへのアクセスが集中するとシステムのレスポンス低下や、最悪システムダウンという状態にもなりかねません。 そこでAWSのリードレプリカは。。。 <<「DBへのアクセスってSELECTがかなりの割合を占めるんだよね?」 <<「だったら1つのDBで全部の処理をやるんじゃなくて、SELECTだけ複製したDBに回せば負荷減るんじゃない?」 ....ということをしてくれるのです。

リードレプリカは1つのRDSインスタンスに対して5つまで生成することができ、生成元RDSインスタンス(以降:マスタDB)と常に同期を取り続けます。

「SELECT」だけレプリカに問い合わせて、「INSERT」「UPDATE」「DELETE」はマスタDBで処理するようにプログラムすることで、マスタDBの負荷を減らし、より多くのアクセスを捌くことができるようになります。


もちろん、リードレプリカには気をつけないといけない部分もあります。

①レプリカとマスタDBとの同期に若干のラグが発生する。 ⇒これはリードレプリカを使う際の避けようがない副作用で、ラグを最小にする為に「レプリカのスペック≧マスタDBのスペック」にする必要があります。 ②トランザクションを使っている場合、同一トランザクション内は同じ参照先にする必要がある。 ⇒トランザクション中は更新情報が同期されません(コミットされてから同期されます)ので、そのトランザクション内で更新内容をレプリカからSELECTしようとしてもできません。 トランザクション中に更新情報をSELECTしたい場合はマスタDBからする必要があります。

このようにリードレプリカとトランザクションを併用する場合にはマスタDBを参照する必要があることに注意が必要です。


【======実装======】

AWSのコンソール上でリードレプリカを作成する方法については色々なサイトで説明されているので今回はスクリーンショットで簡単に概要だけ説明します。

blog_2013-07-29

①AWSコンソールにログインをしてRDSのメニューを開く。

②INSTANCEを開いてレプリカを生成したいRDSインスタンスを選択する。

③画面上部の「INSTANCE ACTIONS」から「Create Read Replica」を実行する。

※マスタDBと同等以上のスケールでインスタンスを生成すること


続いてFuelPHP上での実装についてです。

Fuelのapp/config内にあるdb.phpに以下の記述を追加します。(通常はdefault設定しかないのをreplica1設定を追記)

'replica1' => array(  
  'type' => 'pdo',  
  'connection' => array(  
    'dsn' => 'mysql:host=*****-replica.********.ap-northeast-1.rds.amazonaws.com;dbname=*******',//RDSインスタンスEndpoint  
    'username' => '*******', //DBログインユーザー名  
    'password' => '*******', //DBログインパスワード  
    'persistent' => false,  
    'compress' => false,  
  ),  
  'identifier' => '`',  
  'table_prefix' => '',  
  'charset' => 'utf8',  
  'enable_cache' => true,  
  'profiling' => false,  
),  

これで準備はOKです。

では実際にSELECT文でアクセスしてみましょう。

//default設定を参照しにいく$sql = "SELECT * FROM mst_users WHERE user_id=12345";  
$master_data = \DB::query($sql)->execute()->as_array();   
  
//replica1設定を参照しにいく  
$sql = "SELECT * FROM mst_users WHERE user_id=23456";  
$replica_data = \DB::query($sql)->execute('replica1')->as_array();

たったこれだけです。

応用としてこのような書き方で複数のレプリカを使用することもできると思います。

//replica1~replica5をランダムで参照しにいく  
$sql = "SELECT * FROM mst_users WHERE user_id=12345";  
$replica = 'replica'.mt_rand(1,5)%5 + 1;  
$replica_data = \DB::query($sql)->execute($replica)->as_array();   

リードレプリカは簡単に負荷分散ができる点が魅力だと思います。

アクセス数やデータ量にお悩みの際には解決案の1つにしてみてはいかがでしょうか。