redis 冗長化&自動フェールオーバ環境の構築
redis を複数インスタンス起動させ、レプリケーション(データ同期)させます
フェールオーバには redis-sentinel を採用し master の異常検知で自動に切り替えます
redis-sentinel は、redis 2.4.16 または 2.6.0-rc6 以降のバージョンから利用できます
こちらの 公式ドキュメント も参考にしてください
redis 冗長化環境の概要
今回は、 redis を3インスタンス立ち上げ、
1インスタンスを master(読み書き可)、残りを slave(参照のみ)とするケースにしています。
また死活監視には redis-sentinel を利用し、
master に異常を検知したら slave を master に切り替えます
誤った master 昇格を防ぐ目的に、sentinelも 3インスタンス立ち上げます
(3インスタンス中2インスタンスの異常判定でフェールオーバさせます)
なお、混乱を避けるため先に導入した redis は利用せず、すべて新規インスタンスで構築しています
こんな感じです
redis 設定ファイル
1インスタンスごとに設定ファイルが必要です
初期導入した redis 設定ファイルをコピーして利用します
$ sudo cp -p /etc/redis/redis.conf /etc/redis/redis_1.conf $ sudo cp -p /etc/redis/redis.conf /etc/redis/redis_2.conf $ sudo cp -p /etc/redis/redis.conf /etc/redis/redis_3.conf
インスタンスごとにポート、ログファイル、データファイルなどを変更していきます
redis_1.conf
pidfile /var/run/redis/redis_1.pid port 6381 logfile "/var/log/redis/redis_1.log" dbfilename "dump_redis_1.rdb"
redis_2.conf
pidfile /var/run/redis/redis_2.pid port 6382 logfile "/var/log/redis/redis_2.log" dbfilename "dump_redis_2.rdb"
redis_3.conf
pidfile /var/run/redis/redis_3.pid port 6383 logfile "/var/log/redis/redis_3.log" dbfilename "dump_redis_3.rdb"
redis の起動スクリプトの準備
こちらも、先にインストールした redis 起動スクリプトをコピーして利用します
なお各OSで起動スクリプト形式・場所が違うので適宜変更してください
[CentOS 5/6, Debian6/7, Ubuntu]
$ sudo cp -p /etc/init.d/redis /etc/init.d/redis_1 $ sudo cp -p /etc/init.d/redis /etc/init.d/redis_2 $ sudo cp -p /etc/init.d/redis /etc/init.d/redis_3
インスタンスごとのポートとプロセスIDファイルを設定します
init.d/redis_1
REDISPORT=6381 PIDFILE=/var/run/redis/redis_1.pid CONF="/etc/redis/redis_1.conf"
init.d/redis_2
REDISPORT=6382 PIDFILE=/var/run/redis/redis_2.pid CONF="/etc/redis/redis_2.conf"
init.d/redis_3
REDISPORT=6383 PIDFILE=/var/run/redis/redis_3.pid CONF="/etc/redis/redis_3.conf"
Debian/Ubuntu 系の場合は、各インスタンスに合わせ Provides で名前も変更してください
# Provides: redis_N
[CentOS 7]
自動起動方式が CentOS 7 以降、変更されています
$ sudo cp -p /usr/lib/systemd/system/redis.service /usr/lib/systemd/system/redis_1.service $ sudo cp -p /usr/lib/systemd/system/redis.service /usr/lib/systemd/system/redis_2.service $ sudo cp -p /usr/lib/systemd/system/redis.service /usr/lib/systemd/system/redis_3.service
redis_1.service
ExecStart=/usr/bin/redis-server /etc/redis/redis_1.conf --daemonize no
redis_2.service
ExecStart=/usr/bin/redis-server /etc/redis/redis_2.conf --daemonize no
redis_3.service
ExecStart=/usr/bin/redis-server /etc/redis/redis_3.conf --daemonize no
redis の自動起動(サービス)登録と起動確認
redis をサービスとして登録し、起動を確認します
[CentOS 5/6, Debian6/7, Ubuntu]
$ sudo chkconfig redis_1 on $ sudo chkconfig redis_2 on $ sudo chkconfig redis_3 on $ sudo /etc/init.d/redis_1 start $ sudo /etc/init.d/redis_2 start $ sudo /etc/init.d/redis_3 start
[CentOS 7]
$ sudo systemctl enable redis_1.service $ sudo systemctl enable redis_2.service $ sudo systemctl enable redis_3.service $ sudo systemctl start redis_1.service $ sudo systemctl start redis_2.service $ sudo systemctl start redis_3.service
CentOS 7で、以下メッセージが表示された場合はクリーンを実行してください
Warning: Unit file of redis_1.service changed on disk, 'systemctl daemon-reload' recommended.
$ sudo systemctl daemon-reload
redis の実行プロセスが表示されることを確認します
インストールしたパス(/usr/bin, /usr/sbin もしくは /usr/local/bin)で起動されてます
$ ps -ef | grep redis root 1593 1 0 15:50 ? 00:00:08 /usr/bin/redis-server 127.0.0.1:6381 root 1594 1 0 15:50 ? 00:00:08 /usr/bin/redis-server 127.0.0.1:6382 root 1595 1 0 15:50 ? 00:00:08 /usr/bin/redis-server 127.0.0.1:6383
ログファイルが作成されていることを確認します
$ ls -l /var/log/redis/ -rw-r--r-- 1 redis redis 36860 11月 18 08:17 2015 redis.log -rw-r--r-- 1 root root 36860 11月 19 13:07 2015 redis_1.log -rw-r--r-- 1 root root 20085 11月 19 13:07 2015 redis_2.log -rw-r--r-- 1 root root 23153 11月 19 13:07 2015 redis_3.log
プロセスファイル/ダンプファイルが作成されていることを確認します
$ ls -l /var/run/redis/ -rw-r--r-- 1 root root 18 11月 18 08:17 2015 dump_redis.rdb -rw-r--r-- 1 root root 18 11月 19 21:15 2015 dump_redis_1.rdb -rw-r--r-- 1 root root 18 11月 19 21:15 2015 dump_redis_2.rdb -rw-r--r-- 1 root root 18 11月 19 21:15 2015 dump_redis_3.rdb -rw-r--r-- 1 root root 5 11月 18 08:17 2015 redis.pid -rw-r--r-- 1 root root 5 11月 19 21:15 2015 redis_1.pid -rw-r--r-- 1 root root 5 11月 19 21:15 2015 redis_2.pid -rw-r--r-- 1 root root 5 11月 19 21:15 2015 redis_3.pid
すべての redis インスタンスに接続できることを確認します
この時点では、すべてのインスタンスが master で起動されています
redis_1の確認
$ redis-cli -p 6381 info | egrep 'role|port' tcp_port:6381 role:master
redis_2の確認
$ redis-cli -p 6382 info | egrep 'role|port' tcp_port:6382 role:master
redis_3の確認
$ redis-cli -p 6383 info | egrep 'role|port' tcp_port:6383 role:master
redis 冗長化の確認
2インスタンスを slave モードに切り替えて、redis が冗長化されるか確認します
6382/6383ポートの redis を slave に切り替えます
$ redis-cli -p 6382 slaveof 127.0.0.1 6381 $ redis-cli -p 6383 slaveof 127.0.0.1 6381
正しく slave に切り替えられたか確認します
6381 が role:master、その他が role:slave でレスポンスされていることを確認します
$ redis-cli -p 6381 info | grep role role:master $ redis-cli -p 6382 info | grep role role:slave $ redis-cli -p 6383 info | grep role role:slave
master に値をセットし、slave 側へ反映されることを確認します
$ redis-cli -p 6381 set hoge on OK $ redis-cli -p 6382 get hoge "on" $ redis-cli -p 6383 get hoge "on" $ redis-cli -p 6381 del hoge (integer) 1 $ redis-cli -p 6382 get hoge (nil) $ redis-cli -p 6383 get hoge (nil)
フェールオーバ環境の構築
さて、ここからが自動フェールオーバーの構築になります
redis-sentinel を利用して redis のフェールオーバ設定をおこないます
redis-sentinel のインストール
redis をパッケージ導入した場合は、
redis-sentinel も一緒にインストールされるため次の章に進んで構いません
ソースから導入した場合は、
以下のように redis-2.8.*/src 配下の redis-sentinel (バイナリファイル)をコピーします
$ sudo cp -p ./redis-2.8.*/src/redis-sentinel /usr/local/bin/
redis-sentinel の設定ファイル
こちらも、各インスタンスごとに設定ファイルが必要です
既存の redis-sentinel 設定ファイルをコピーし、各インスタンス用に起動ポートなどを変更します
[ソースインストール]
展開したソース配下にある既存の設定ファイルをコピーして利用します
$ sudo cp -p ./redis-2.8.*/sentinel.conf /etc/redis/sentinel_1.conf
[パッケージインストール]
インストールされた既存の設定ファイルを探してコピーします
$ locate sentinel.conf /etc/redis/sentinel.conf $ sudo cp -p /etc/redis/sentinel.conf /etc/redis/sentinel_1.conf
起動ポートとフェールオーバの設定をおこないます
以下例は、5秒間 master が応答がなければ slave を master に昇格させる設定となります
また、(別筐体のサーバで)分散稼働させる場合は IPアドレス/ポート を適切な値に置き換えることが必要です
$ sudo vi /etc/redis/sentinel_1.conf daemonize yes port 26381 sentinel monitor mymaster 127.0.0.1 6381 2 sentinel down-after-milliseconds mymaster 5000
上記の ”sentinel monitor mymaster 127.0.0.1 6381 2” の最後尾に記述している
”2″ の値が、3インスタンス中の2インスタンス(=多数決)で判定する閾値となります
もし sentinel を5インスタンス稼働させ、うち3インスタンスで判定する場合は “3” と設定します
作成した設定ファイルをコピーします
$ sudo cp -p /etc/redis/sentinel_1.conf /etc/redis/sentinel_2.conf $ sudo cp -p /etc/redis/sentinel_1.conf /etc/redis/sentinel_3.conf
2インスタンス用にポートを変更します
$ sudo vi /etc/redis/sentinel_2.conf port 26382
3インスタンス用にポートを変更します
$ sudo vi /etc/redis/sentinel_3.conf port 26383
redis-sentinel は稼働中、redis 設定ファイルに書き込みをおこないます
所有オーナーと書き込み権限を変更しておきます
$ sudo chmod 644 /etc/redis/sentinel_1.conf $ sudo chmod 644 /etc/redis/sentinel_2.conf $ sudo chmod 644 /etc/redis/sentinel_3.conf $ sudo chown redis:redis /etc/redis/sentinel_1.conf $ sudo chown redis:redis /etc/redis/sentinel_2.conf $ sudo chown redis:redis /etc/redis/sentinel_3.conf
redis-sentinel の起動スクリプトの準備
自動起動用のスクリプトファイルを用意します
[CentOS 5/6, Debian6/7, Ubuntu]
$ sudo cp -p /etc/init.d/redis-server-1 /etc/init.d/redis-sentinel-1
[CentOS 7]
$ sudo cp -p /usr/lib/systemd/system/redis-sentinel.service /usr/lib/systemd/system/redis-sentinel-1.service
各OSに対応する起動ファイルの設定をおこないます
[CentOS 5/6]
init.d/redis-sentinel-1
# chkconfig: 345 85 15 # description: sentinel-1 # processname: sentinel-1 # pidfile: /var/run/redis/sentinel-1.pid # config: /etc/redis/sentinel-1.conf name="sentinel-1" pidfile="/var/run/redis/sentinel-1.pid" REDIS_CONFIG="/etc/redis/sentinel-1.conf" [ -e /etc/sysconfig/redis-sentinel ] && . /etc/sysconfig/redis-sentinel
[CentOS 7]
redis-sentinel-1.service
ExecStart=/usr/bin/redis-sentinel /etc/redis/sentinel-1.conf --daemonize no ExecStop=/usr/bin/redis-shutdown sentinel-1
[Debian6/7, Ubuntu]
init.d/redis-sentinel-1
### BEGIN INIT INFO # Provides: redis-sentinel-1 # Required-Start: $syslog $remote_fs bootlogs # Required-Stop: $syslog $remote_fs # Should-Start: $local_fs # Should-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Description: Redis Sentinel is a KVS server. # Short-Description: sentinel-1 ### END INIT INFO DAEMON=/usr/local/bin/redis-sentinel DAEMON_ARGS=/etc/redis/sentinel-1.conf NAME=sentinel-1 DESC=sentinel-1 PIDFILE=$RUNDIR/redis-sentinel-1.pid
redis-sentinel の起動確認
起動スクリプトで redis-sentinel−1 を起動します
[CentOS 5/6, Debian6/7, Ubuntu]
$ sudo /etc/init.d/redis-sentinel-1 start
[CentOS 7]
$ sudo systemctl start redis-sentinel-1.service
起動を確認します
$ ps -ef | grep redis-sentinel redis 1679 1 0 19:38 ? 00:00:18 /usr/bin/redis-sentinel *:26381
起動確認できたら起動ファイルをコピーし、残りのインスタンス分を用意します
[CentOS 5/6, Debian6/7, Ubuntu]
$ sudo cp -p /etc/init.d/redis-sentinel-1 /etc/init.d/redis-sentinel-2 $ sudo cp -p /etc/init.d/redis-sentinel-1 /etc/init.d/redis-sentinel-3
[CentOS 7]
$ sudo cp -p /usr/lib/systemd/system/redis-sentinel-1.service /usr/lib/systemd/system/redis-sentinel-2.service $ sudo cp -p /usr/lib/systemd/system/redis-sentinel-1.service /usr/lib/systemd/system/redis-sentinel-3.service
各インスタンス用に起動ファイルを変更します
sentinel-1 と記載されている箇所を、すべて sentinel-2(またはsentinel-3)に変更します
[CentOS 5/6, Debian6/7, Ubuntu]
$ sudo vi /etc/init.d/redis-sentinel-2 :%s/sentinel_1/sentinel_2/g $ sudo vi /etc/init.d/redis-sentinel-3 :%s/sentinel_1/sentinel_3/g
[CentOS 7]
$ sudo vi /usr/lib/systemd/system/redis-sentinel-2.service :%s/sentinel_1/sentinel_2/g $ sudo vi /usr/lib/systemd/system/redis-sentinel-3.service :%s/sentinel_1/sentinel_3/g
起動スクリプトで redis-sentinel-2/3 を起動します
[CentOS 5/6, Debian6/7, Ubuntu]
$ sudo /etc/init.d/redis-sentinel-2 start $ sudo /etc/init.d/redis-sentinel-3 start
[CentOS 7]
$ sudo systemctl start redis-sentinel-2.service $ sudo systemctl start redis-sentinel-3.service
起動を確認します
$ ps -ef | grep redis-sentinel redis 1679 1 0 19:38 ? 00:00:18 /usr/bin/redis-sentinel *:26381 redis 1694 1 0 19:38 ? 00:00:18 /usr/bin/redis-sentinel *:26382 redis 1708 1 0 19:38 ? 00:00:17 /usr/bin/redis-sentinel *:26383
redis-sentinel の動作確認
master を終了させ、自動で slave が master に昇格されることを確認します
現在のステータスを確認します
ポート6381が master 、その他が slave となっています
$ redis-cli -p 6381 info | grep role role:master $ redis-cli -p 6382 info | grep role role:slave $ redis-cli -p 6383 info | grep role role:slave
master を終了させ、5秒後に slave が master に昇格されることを確認します
$ redis-cli -p 6381 shutdown
5秒ほど待ってから
$ redis-cli -p 6381 info | grep role Could not connect to Redis at 127.0.0.1:6381: Connection refused $ redis-cli -p 6382 info | grep role role:master $ redis-cli -p 6383 info | grep role role:slave
ポート6381を再度起動させ slave で起動されることを確認します
$ sudo /etc/init.d/redis-server-1 start
5秒以上経過してから
$ redis-cli -p 6381 info | grep role role:slave $ redis-cli -p 6382 info | grep role role:master $ redis-cli -p 6383 info | grep role role:slave
redis-sentinel の自動起動設定
サーバの再起動でも自動でサービス起動、停止するようにします
[CentOS 5/6]
$ sudo chkconfig redis-sentinel-1 on $ sudo chkconfig redis-sentinel-2 on $ sudo chkconfig redis-sentinel-3 on $ chkconfig --list | grep redis
[CentOS 7]
$ sudo systemctl enable redis-sentinel-1.service $ sudo systemctl enable redis-sentinel-2.service $ sudo systemctl enable redis-sentinel-3.service $ sudo systemctl list-unit-files | grep redis
[Debian6/7, Ubuntu]
$ sudo sysv-rc-conf redis-sentinel-1 on $ sudo sysv-rc-conf redis-sentinel-2 on $ sudo sysv-rc-conf redis-sentinel-3 on $ sysv-rc-conf --list | grep redis
redis/redus-sentinel の自動起動確認
サーバを再起動させ、redis 及び redis-sentinel が自動起動されることを確認します
$ sudo shutdown -r now
サーバ再起動後、
$ ps -ef | grep redis redis 1593 1 0 18:08 ? 00:00:24 /usr/bin/redis-server 127.0.0.1:6381 redis 1594 1 0 18:08 ? 00:00:24 /usr/bin/redis-server 127.0.0.1:6382 redis 1595 1 0 18:08 ? 00:00:24 /usr/bin/redis-server 127.0.0.1:6383 redis 1601 1 0 18:08 ? 00:00:38 /usr/bin/redis-sentinel *:26381 redis 1602 1 0 18:08 ? 00:00:38 /usr/bin/redis-sentinel *:26382 redis 1604 1 0 18:08 ? 00:00:42 /usr/bin/redis-sentinel *:26383
再起動されていることを確認で終了です