Redisのフェールオーバー環境を構築する（その３）

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

　[（その１）：Redisのインストール](http://qiita.com/KurosawaTsuyoshi/items/f8719bf7c3a10d22a921)
　[（その２）：Redisの冗長化](http://qiita.com/KurosawaTsuyoshi/items/936c32bb8947fb907ef5)
　**（その３）：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 と一緒にインストールされますが、もし存在しない場合はコピーして利用します

```bash
$ 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 とします

```bash
[ソースインストールの場合]
$ 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 6381` の **IPアドレスとポート番号** を適切な値に設定することが必要です
　　なお Redis-SentinelのIP・ポートではありません
　　Redis 本体の Master のIPアドレスとポートを指定してください

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

```bash
$ sudo vi /etc/redis/26381.conf
```
```text
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”の最後尾にある数値（＝２）が、3インスタンス中の2インスタンスで判定（＝多数決）という指定になります
5インスタンス稼働させて、うち3インスタンスで判定する場合は "3" となります

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

```bash
$ 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とポートなので変更しません

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

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

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

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

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

```bash
$ 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　の起動スクリプトを用意します

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

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

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

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

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

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

## Redis-Sentinel の起動確認
起動スクリプトで redis-sentinel_1 を起動します

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

起動を確認します

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

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

```bash
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
```

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

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

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

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

起動を確認します

```bash
$ 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 が自動で起動、停止するようにします

```bash
$ 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 が自動起動されることを確認します  

```bash
$ reboot
```

サーバ再起動後、

```bash
$ 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 となっています

```bash
$ 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 を終了させ、５秒後に slave が master に昇格されることを確認します

```bash
$ redis-cli -p 6381 -a hoge shutdown

５秒ほど待ってから

$ 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 で起動されることを確認します

```bash
$ sudo service redis_1 start
```

5秒以上経過してから

```bash
$ 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
```

以上です