CakePHP、MySQLでレプリケーションした日記 | エモンのブログ(スマホアプリ作成日記)

エモンのブログ(スマホアプリ作成日記)

エモンのブログです。

GooglePlayとAppStoreにアプリをリリースしてます。
「詰将棋パラダイス」4500問無料で公開。
「みんなのしょうぎ」投票型の将棋対局。いずれもソーシャルアプリなので、ソーシャルゲーム作成に興味があるかたは是非ご覧ください。

サーバが落ちまくって発狂しました。まさか個人で運用しているサーバでレプリケーションすることになるとは思わなかったですね。
負荷を見ているとやはりというか、DBの負荷が大量でWEBサーバは余裕がありそうでした。
なのでDBのインスタンスを増やしてレプリケーションすることにしました。バックアップ体制も整うことですし。


(0)レプリケーションってなんなのか
DBの負荷分散、あるいはバックアップとしてDBのサーバをもう一つ追加します。
追加したDBのほうをSlaveと以下表記します。SlaveからMasterのバイナリログを見て同期を取ります。
更新はMasterのDBを使いますが、参照はSlaveのほうを見る事にすれば負荷が分散されます。


(1)Slave用のサーバを用意する
Slave用のサーバを用意しました。通常のサーバ用意するのと同じです。


(2)Masterのmy.cnfを修正
Masterの/etc/my.cntの[mysqld]の項目に以下の2つを追加
[mysqld]
log-bin
server-id=1

server-idの値は適当に1でいいでしょう。


(3)replユーザを作成する
SlaveサーバからMasterのバイナリログを見るためのユーザを作成します。
Master側のDBから
mysql > GRANT REPLICATION SLAVE ON *.* TO repl@SlaveのIPアドレス IDENTIFIED BY 'パスワード';



(4)データベースのバックアップ
tarファイルを作るほうがいいんでしょうが、失敗したので普通にdumpしました。
・一旦書き込みをロックします。
mysql > FLUSH TABLES WITH READ LOCK;

・dumpを取ります。
mysqldump -u root --password=パスワード -x --databases DB名 > /home/admin/dump.sql

・マスターのバイナリログの位置を確認する
mysql > SHOW MASTER STATUS;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| XXX | YYY | | |
+-------------------+----------+--------------+------------------+



(5)ファイル移動
SCPでdumpファイルをSlaveサーバへ移動させます
scp /home/admin/dump.sql root@SlaveのIPアドレス:/home/admin



(6)Slaveにてdumpの展開
mysql -u root DB名 < /home/admin/dump.sql



(7)Slaveのmy.confを修正
文字コードなどもMasterと合わせてます。
先ほど作成したreplユーザの情報を登録します。
[mysqld]
server-id=2
replicate-do-db=DB名
master-host=マスターのホスト名
master-user=repl
master-password=password



(8)バイナリログの位置をSlaveに登録
(4)で確認した値が必要になります。
mysql>
CHANGE MASTER TO
MASTER_HOST='MasterのIPアドレス',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_PORT=3306,
MASTER_LOG_FILE='XXX',
MASTER_LOG_POS=YYY;



(9)お互いのmysqldを再起動する
service mysqld restart



(10)レプリケーション開始
Slave側で
mysql> START SLAVE;



(11)レプリケーションの状態を確認
show slave status\G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

この2つがYESでないと正常でないのでサービスを開始できません。
サーバ構成が間違っている場合(テーブルが足りないなど)Slave_SQL_Running:Noになってました。
またMaster,Slaveどちらかのみmysqldの再起動をするとSlave_IO_Running: Noになります。お互いに再起動しておきましょう。
スレーブをリセットするには
reset slave;

大丈夫そうならサービスを再開します。
Master側で
UNLOCK TABLES;



(12)CakePHPからSlaveサーバを見るためのユーザ作成

CakePHPkからSlaveDBを見るためのユーザを作成します。
cakeusr@"%"にしておかないと別IPアドレスからアクセスできません。
またSlaveではselect権限だけにしておきます。
Slave側で
mysql > GRANT SELECT ON *.* TO cakeusr@"%" IDENTIFIED BY 'password';
mysql > FLUSH PRIVILEGES;



(13)CakePHP対応
database.phpにslaveサーバ情報を追加する。
var $slave = array(
'driver' => 'mysql',
'persistent' => false,
'host' => 'SlaveのIPアドレス',
'login' => 'cakeusr',
'password' => 'password',
'database' => 'DB名',
'prefix' => '',
'encoding' => 'UTF-8',
);

またModelクラスで適宜
$this->useDbConfig = 'slave';

とすればSlaveサーバが使われます。
app_modelにメソッド作っておくのが自然でしょうかね。