Nullyのぶろぐ

仙台から東京へ転勤したエンジニアのブログ

Zend Frameworkdを使ってMySQLレプリケーションサーバーに対応する

タイトルの通りMySQLレプリケーションサーバーへの対応を考えてみました!

手順的には比較的簡単に対応出来きたのでメモメモ[wp_emoji2 code="d214" alt="鉛筆"]

サーバー構成

MySQLはMasterとSlaveの2台を準備し、プライベートIPで結ばれている状態のものです。

WebサーバーからはプライベートIPでSlaveサーバーにアクセスし、データを取得します。

WebサーバーはApache2系をインストールしていて、リバースプロキシなどの設定はしていないことを仮定しています。

図に表すとこういう状態になります。(あってるかな?)

レプリケーションの図

MultIDbリソースを設定する

ZendFrameworkにはDBリソースを複数設定できるMultiDBリソースというものがあります。

これを利用し、MasterとSlaveを変えていきます。

まずはリソース設定を書き足します。

// configs/application.ini

resources.multidb.master.adapter = "Pdo_Mysql"

resources.multidb.master.host = "192.168.0.1"

resources.multidb.master.username = "master_user"

resources.multidb.master.password = "master_password"

resources.multidb.master.dbname = "master_db"

resources.multidb.slave.adapter = "Pdo_Mysql"

resources.multidb.slave.host = "192.168.0.2"

resources.multidb.slave.username = "slave_user"

resources.multidb.slave.password = "slave_password"

resources.multidb.slave.dbname = "slave_db"

上記の通り、MasterとSlaveの設定を分けてかけます。

なので、もひとつほしいれす><という場合は、multidbの名前空間を増やしてあげる事で対応も可能です。

BootstrapでSlaveのデータソースを設定する

後ほどZend_Db_Table_Abstractクラスを継承したクラスも出てきますが、先にSlaveサーバーへの設定を行なっておくと、保存するメソッドだけを上書きすればよいので先に書いておきます。

// Bootstrap.php

protected function _initSlaveDataSource() {

    $multiDB= $this->bootstrap("multidb")->getResource("multidb");

    $slave_resource = $multiDB->getDb("slave"); // application.iniにて設定した名前空間

    Zend_Db_Table_Abstract::setDefaultAdapter($slsave_resource);

    return $slave_resource;

}

Zend_Db_Table_Abstract::setDefaultAdapter()を呼び出して、デフォルトで利用するアダプタ(データソース)を設定しておきます。

これで素直にselectやfetchRowなどを行うときはSlaveサーバーの設定を見るようになります。

Zend_Db_Table_Abstractを継承したクラスを作る

保存処理はMasterに対して行いたいので、保存処理だけメソッドを上書きしてしまいます。

abstract class Sample_DbTable_Abstract extends Zend_Db_Table_Abstract {

    public funciton insert() {

        $this->_setMasterConnection();

        // 他にやることなど

        parent::insert();

    }

    // updateは省略します。

    protected function _setMasterConnection() {

        // すでにMasterのアダプター(データソース)が設定されているかのチェックも一応必要ですが、省略します。

        $bootstrap = Zend_Controller_Front::getInstance()->getParam("bootstrap");

        $multiDB = $bootstrap->bootstrap("multidb")->getResource("multidb");

        $this->_db = $multiDB->getDb("master"); // application.iniに設定した名前空間

    }

}

このような感じに。

Zend_Db_Table_Row_Abstractクラスは、保存(更新・追加)を行った後に、自分自身のデータのリフレッシュ(テーブルデータの更新ではなく、_dataの構築)を行います。(テーブルデーゲートウェイパターンによるものでしょうか?)

なので、Masterに対して更新を行い、Slaveからデータを引き出そうとすると「Can not refresh〜〜〜」とか出てきます。

これはお察しの通り、Slaveからデータを引き出そうとするがデータが無いため起こるエラーです。(他の場合も起こりますが><)

これでひとまず対応という感じになります。

終わりに

久しぶりな更新の上に、久しぶりのZFネタで、ざざざーーーーっと書きましたが、多分大丈夫です!きっと[wp_emoji2 code="d160" alt="double exclamation"] [wp_emoji2 code="d160" alt="double exclamation"] [wp_emoji2 code="d160" alt="double exclamation"] [wp_emoji2 code="d232" alt="がまん顔"]