CakePHPでSELECTの時だけリードレプリカから情報を取得するようにする

CakePHP2

サービス全体の流入が大きくなってきた時、DBの性能が気になって来ることがあります。mysqlとかであれば、リードレプリカからSelectをすることで負荷を分散することができます。

CakePHPでSELECTの時だけ指定したDBに接続してSELECTする方法を書きます。

 

■database.phpファイルの記述

リードレプリカ用の設定を記述します。以下のように、通常の接続先とリードレプリカ用の接続先をdatabase.phpに記述します。

// デフォルトの接続先
public $default = array(
    'datasource' => 'Database/Mysql',
    'persistent' => false,
    'host' => 'localhost',
    'login' => 'loginuser',
    'password' => '',
    'database' => 'database_name',
    'prefix' => '',
    //'encoding' => 'utf8',
);

// リードレプリカ用の接続先
public $default_read = array(
    'datasource' => 'Database/Mysql',
    'persistent' => false,
    'host' => 'localhost_readreplica',
    'login' => 'loginuser_read',
    'password' => '',
    'database' => 'database_name_readreplica',
    'prefix' => '',
    //'encoding' => 'utf8',
);

 

 

■AppModelのbeforeFindとafterFindメソッドをオーバーライド

AppModel.phpに以下を記述します。そうすると、自動的にselectだけはレプリカから取得されるようになります。 あとは、このAppModelを継承してモデルを作成すれば、完成です。

/**
* SELSECTをする前に実行される関数です。
* セレクト直前にリードレプリカ側を見るように接続を変更しています。
*/
public function beforeFind($queryData) {
    $this->useDbConfig = 'default_read';
    foreach ($this->belongsTo as $btModelName => $btModelData) {
        $this->{$btModelName}->useDbConfig = 'default_read';
    }
    return $queryData;
}

/**
* SELECTが完了するときに実行する関数です。
* リードレプリカから、通常の接続に戻すように変更しています。
*/
public function afterFind($results, $primary = false) {
    $this->useDbConfig = 'default';
    foreach ($this->belongsTo as $btModelName => $btModelData) {
        $this->{$btModelName}->useDbConfig = 'default';
    }
    return $results;
}

現状は負荷が低くて同じDBに接続するようにしていても、将来のことを考えて一旦実装しておくのもいいと思います。数少ないDBの負荷分散方法です。