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
再起動されていることを確認で終了です