稼動中の ttserver をデュアルマスタ化した。
現状
192.168.1.1:1978 で ttserver が稼動中。
バックアップも何もないので、二重化したい。
目標
192.168.1.1:1978 (Server.A) と 192.168.1.2:1978 (Server.B) でデュアルマスタ化して、バックアップついでに可用性も確保する。
方法
Server.A の起動コマンドを確認する
まず、 Server.A は -sid -ulog オプションがついている必要がある。
ついていなければ、再起動する。
再起動は十分早いので、稼動中でも別に良い……んじゃ……ないかな。
# Server.A の起動コマンド /usr/local/bin/ttserver \ -host 192.168.1.1 \ -port 1978 \ -sid 1 \ -ulog /var/ttserver/ulog-1 \ /var/ttserver/casket.tch
Server.A のバックアップを取る
まずバックアップスクリプトを作成する。
スクリプトの場所はどこでもいい。
ここでは /path/to/script.sh とする。
また、バックアップファイルが作成されるディレクトリを、 /path/to/backup とする。
#!/bin/sh BACKUP=/path/to/backup # バックアップディレクトリ SRCPATH="$1" BASENAME=`basename "$SRCPATH"` DESTPATH="$BACKUP/$BASENAME.$2" rm -f "$DESTPATH" cp -f "$SRCPATH" "$DESTPATH"
バックアップする。
バックアップ作成中は、データベースがロックされるので注意。
/usr/local/bin/tcrmgr copy -port 1978 192.168.1.1 '@/path/to/script.sh'
これで、 /path/to/backup/casket.tch.XXX が作成される。
なお、 XXX は 16 桁のタイムスタンプ。
これをそのまま Server.B に送る。
Server.B を設定する
Server.A から送られてきたバックアップファイルを、 /path/to/backup/casket.tch.XXX とする。
BACKUP=/path/to/backup/casket.tch.XXX # データベースファイルと更新ログを置くディレクトリを作成。 mkdir -p /var/ttserver/ulog-2 # ファイル名が cas.ket.tch.XXX である等、 . が 2 つ以上含まれている場合は失敗するので注意。 BASENAME=`basename "$BACKUP" | cut -d. -f1,2` RTS=`basename "$BACKUP" | cut -d. -f3` mv $BACKUP /var/ttserver/$BASENAME echo "$RTS" > /var/ttserver/2.rts # 起動。 /usr/local/bin/ttserver \ -host 192.168.1.2 \ -port 1978 \ -sid 1 \ -ulog /var/ttserver/ulog-2 \ -mhost 192.168.1.1 \ -mport 1978 \ -rts /var/ttserver/2.rts \ /var/ttserver/casket.tch
これで Server.A => Server.B のレプリケーションが出来る。
Server.A を設定する
Server.B => Server.A のレプリケーションを設定する。
# これだけ。 /usr/local/bin/tcrmgr setmst -port 1978 -mport 1978 192.168.1.1 192.168.1.2
終了
バックアップ作成さえ何とかなれば、無停止でデュアルマスタ構成に出来るよ!
やったね!
今後の課題
バックアップの作成がネックだけど、 cp
じゃなくて LVM のスナップショットにすれば、何とか出来るかも。
運用について
運用時は、常に Server.A に対して更新するようにする。
Server.A に対する更新が失敗した場合のみ、 Server.B に対して更新する。
<?php function get_tt() { try { return new TokyoTyrant('192.168.1.1', 1978); } catch (Exception $e) { try { return new TokyoTyrant('192.168.1.2', 1978); } catch (Exception $e) { return null; } } }
この程度でいいんじゃないかしら。