Redisのフェールオーバー環境を構築する(その3)


Redis 冗長化 & フェールオーバー環境を CentOS 6.x 上に構築する手順です
手順は3部構成となっており、本稿は Redis-Sentinelによるフェールオーバー環境の構築となります

 (その1):Redisのインストール
 (その2):Redisの冗長化
 (その3):Redis-Sentinelによるフェールオーバー環境の構築

Redisのフェールオーバー環境の概要

死活監視には Redis-Sentinel を利用します
Master に異常が発生したら Slave を Master に自動で昇格させます

誤った昇格を防ぐため、死活監視の Redis-Sentinel も3インスタンス起動させて、多数決(2台/3台)による判定をさせます

起動ファイル ポート 設定ファイル 説明
redis 6379 6379.conf 停止させます。利用しません
redis_1 6381 6381.conf Master
redis_2 6382 6382.conf Slave1
redis_3 6383 6383.conf Slave2
sentinel 26379 - 導入しません。利用しません
sentinel_1 26381 26381.conf 死活監視1
sentinel_2 26382 26382.conf 死活監視2
sentinel_3 26383 26383.conf 死活監視3

フェールオーバ環境の構築

Redis-Sentinel は Redis と一緒にインストールされますが、もし存在しない場合はコピーして利用します

$ which redis-sentinel
/usr/bin/redis-sentinel

表示されたらこの項はスキップしてください。
何も表示されない場合は以下のコマンドでコピーします

[ソースからインストールした場合]
$ sudo cp -p ~/Downloads/redis-3.0.*/src/redis-sentinel /usr/local/bin/

[パッケージからインストールした場合]
$ sudo ln -s /usr/bin/redis-server /usr/bin/redis-sentinel

なお Redis-Sentinel は 実体は Redis-Server です
Redis-Server をコピーしてリネーム、シンボリックリンクを貼る。でもOKだったりします

Redis-Sentinel の設定ファイル

インスタンスごとに設定ファイルが必要です
既存の Redis-Sentinel 設定ファイルをコピーして各インスタンス用に設定します

Redis 本体同様、ファイル名は ポート番号.conf とします

[ソースインストールの場合]
$ sudo cp -p ~/Downloads/redis-3.0.*/sentinel.conf /etc/redis/26381.conf

[パッケージインストールの場合]
$ sudo cp -p /etc/redis-sentinel.conf /etc/redis/26381.conf

起動ポートとフェールオーバの設定をおこないます

以下の例は Master が 5秒間 応答なければ いずれかの Slave を Master に昇格させます

 注意
  Redis 本体を別筐体のサーバなどで分散稼働させる場合は sentinel monitor mymaster 127.0.0.1 6381IPアドレスとポート番号 を適切な値に設定することが必要です
  なお Redis-SentinelのIP・ポートではありません
  Redis 本体の Master のIPアドレスとポートを指定してください

 重要
  パスワードを指定している場合は sentinel auth-pass mymaster hoge の設定も必要です

$ sudo vi /etc/redis/26381.conf
daemonize yes
port 26381
pidfile sentinel_26381.pid
dir /var/run/redis
logfile /var/log/redis/26381.log
sentinel monitor mymaster 127.0.0.1 6381 2
sentinel down-after-milliseconds mymaster 5000
sentinel auth-pass mymaster hoge

”sentinel monitor mymaster 127.0.0.1 6381 2”の最後尾にある数値(=2)が、3インスタンス中の2インスタンスで判定(=多数決)という指定になります
5インスタンス稼働させて、うち3インスタンスで判定する場合は "3" となります

残りの Redis-Sentinel 用に、いま作成した設定ファイルをコピーします

$ sudo cp -p /etc/redis/26381.conf /etc/redis/26382.conf
$ sudo cp -p /etc/redis/26381.conf /etc/redis/26383.conf

2インスタンス目の設定をおこないます

 重要
  Sentinel の起動ポートに関連する箇所のみ変更します
  sentinel monitor mymaster 127.0.0.1 6381 2 は Redis 本体のIPとポートなので変更しません

$ sudo vi /etc/redis/26382.conf
port 26382
logfile /var/log/redis/26382.log
pidfile sentinel_26382.pid

3インスタンス目の設定をおこないます

 重要
  こちらも Sentinel のポートとログファイル名のみ変更します

$ sudo vi /etc/redis/26383.conf
port 26383
logfile /var/log/redis/26383.log
pidfile sentinel_26382.pid

Redis-Sentinel は動作中、設定ファイルに書き込みをおこないます
所有オーナーと書き込み権限の変更をしておきます

$ sudo chmod 644 /etc/redis/26381.conf
$ sudo chmod 644 /etc/redis/26382.conf
$ sudo chmod 644 /etc/redis/26383.conf
$ sudo chown redis:redis /etc/redis/26381.conf
$ sudo chown redis:redis /etc/redis/26382.conf
$ sudo chown redis:redis /etc/redis/26383.conf

Redis-Sentinel の起動スクリプト

Redis-Sentinel の起動スクリプトを用意します

[パッケージインストールの場合]

$ sudo cp -p /etc/init.d/redis-sentinel /etc/init.d/redis-sentinel_1
$ sudo vi /etc/init.d/redis-sentinel_1
REDISPORT=26381
pidfile="/var/run/redis/redis_${REDISPORT}.pid"
SENTINEL_CONFIG="/etc/redis/${REDISPORT}.conf"

[ソースインストールの場合]
Redis-Sentinel 用の起動スクリプトは用意されてません
よって Redis 本体の起動スクリプトをコピーして利用します

$ sudo cp -p /etc/init.d/redis_1 /etc/init.d/redis-sentinel_1
$ sudo vi /etc/init.d/redis-sentinel_1
# chkconfig: 345 75 15
REDISPORT=26381
EXEC=/usr/local/bin/redis-sentinel
PIDFILE=/var/run/redis/sentinel_${REDISPORT}.pid

ここからは、ソースインストールもパッケージインストールも共通です
redis-sentinel_1 をコピーして編集します

$ 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
$ sudo vi /etc/init.d/redis-sentinel_2
# chkconfig: 345 75 15
REDISPORT=26382
$ sudo vi /etc/init.d/redis-sentinel_3
# chkconfig: 345 75 15
REDISPORT=26383

Redis-Sentinel の起動確認

起動スクリプトで redis-sentinel_1 を起動します

$ sudo /etc/init.d/redis-sentinel_1 start

起動を確認します

$ ps -ef | grep redis-sentinel
coco       2359      1  0 00:02 ?        00:00:06 /usr/local/bin/redis-sentinel *:26381 [sentinel]

起動確認できたら起動ファイルをコピーし、残りのインスタンス分を用意します

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

各インスタンス用に起動ファイルを変更します

$ sudo vi /etc/init.d/redis-sentinel_2
REDISPORT=26382
$ sudo vi /etc/init.d/redis-sentinel_3
REDISPORT=26383

起動スクリプトで redis-sentinel_2 / redis-sentinel_3 を起動します

$ sudo /etc/init.d/redis-sentinel_2 start
$ sudo /etc/init.d/redis-sentinel_3 start

起動を確認します

$ ps -ef | grep redis-sentinel
redis      3943      1  0 22:34 ?        00:00:02 /usr/bin/redis-sentinel *:26381 [sentinel]                                                               
redis      3993      1  0 22:38 ?        00:00:01 /usr/bin/redis-sentinel *:26382 [sentinel]                                                               
redis      4031      1  1 22:40 ?        00:00:00 /usr/bin/redis-sentinel *:26383 [sentinel]                                                               

Redis-Sentinel の自動起動設定

サーバの再起動でも Redis-Sentinel が自動で起動、停止するようにします

$ sudo chkconfig redis-sentinel_1 on
$ sudo chkconfig redis-sentinel_2 on
$ sudo chkconfig redis-sentinel_3 on
$ chkconfig --list | grep redis
redis           0:off   1:off   2:off   3:off   4:off   5:off   6:off
redis-sentinel  0:off   1:off   2:off   3:off   4:off   5:off   6:off
redis-sentinel_1    0:off   1:off   2:on    3:on    4:on    5:on    6:off
redis-sentinel_2    0:off   1:off   2:on    3:on    4:on    5:on    6:off
redis-sentinel_3    0:off   1:off   2:on    3:on    4:on    5:on    6:off
redis_1         0:off   1:off   2:on    3:on    4:on    5:on    6:off
redis_2         0:off   1:off   2:on    3:on    4:on    5:on    6:off
redis_3         0:off   1:off   2:on    3:on    4:on    5:on    6:off

自動起動の確認

サーバを再起動させて、Redis 及び Redis-Sentinel が自動起動されることを確認します

$ reboot

サーバ再起動後、

$ ps -ef | grep redis
redis      2038      1  1 22:46 ?        00:00:00 /usr/bin/redis-server 127.0.0.1:6381                                                              
redis      2053      1  0 22:46 ?        00:00:00 /usr/bin/redis-server 127.0.0.1:6382                                                              
redis      2068      1  0 22:46 ?        00:00:00 /usr/bin/redis-server 127.0.0.1:6383                                                              
redis      2083      1  1 22:46 ?        00:00:00 /usr/bin/redis-sentinel *:26381 [sentinel]                                                               
redis      2098      1  0 22:46 ?        00:00:00 /usr/bin/redis-sentinel *:26382 [sentinel]                                                               
redis      2113      1  1 22:46 ?        00:00:00 /usr/bin/redis-sentinel *:26383 [sentinel]                                                               

フェールオーバーの検証

Redis 本体の Master を終了させ、Slave が Master に自動で昇格されることを確認します

現在のステータスを確認します
ポート6381が master 、その他が slave となっています

$ redis-cli -p 6381 -a hoge info | grep role
role:master
$ redis-cli -p 6382 -a hoge info | grep role
role:slave
$ redis-cli -p 6383 -a hoge info | grep role
role:slave

Master を終了させ、5秒後に slave が master に昇格されることを確認します

$ redis-cli -p 6381 -a hoge shutdown

5秒ほど待ってから

$ redis-cli -p 6381 -a hoge info | grep role
Could not connect to Redis at 127.0.0.1:6381: Connection refused
$ redis-cli -p 6382 -a hoge info | grep role
role:master
$ redis-cli -p 6383 -a hoge info | grep role
role:slave

ポート6381を再度起動させ slave で起動されることを確認します

$ sudo service redis_1 start

5秒以上経過してから

$ redis-cli -p 6381 -a hoge info | grep role
role:slave
$ redis-cli -p 6382 -a hoge info | grep role
role:master
$ redis-cli -p 6383 -a hoge info | grep role
role:slave

以上です