Redis Sentinelを構成してみる

# TL;DR

* Redis Sentinelを使用することで、レプリケーションを構成したRedisのマスター障害時に、フェイルオーバーが可能になる
* レプリカがマスターに昇格するが、クライアントからのアクセスを切り替える方法はRedis Sentinelは提供しない
    * いわゆる、VIP的なものはない
    * マスター、レプリカのアクセス先の切り替えは、別途考える必要がある
* マスター、レプリカの他に、Sentinelというプロセスが必要になる
* Redis Sentinelを構成するには、最低5つのRedisプロセスが必要
    * マスター × 1
    * レプリカ × 1
    * Sentinel × 3
* Sentinelプロセスが3つを下回る構成とすることは推奨されない
    * 誤検知防止のため、QUORUMを使用する
* スケールアウトもしたい、という場合はRedis Clusterを検討する


# Redis Sentinel

Redis Sentinelは、Redisに対して高可用性を提供するものです。ドキュメントについては、こちら。

[Redis Sentinel Documentation](https://redis.io/topics/sentinel)

Redis Sentinelの主な特徴は、以下の4つだそうです。

* Monitoring
    * Sentinelは、マスター、スレーブが動作しているかチェックします
* Notification
    * SentinelはAPIを利用して、モニタリングしているRedisに問題が発生した時に、システム管理者や別のプログラムなどに通知することができます
* Automatic failover
    * マスターが動作しない場合、Sentinelはフェイルオーバープロセスを開始し、レプリカを新しいマスターに昇格させます
* Configuration provider
    * Sentinelは、現在のマスターの接続先への問い合わせに答えることができます
    * マスターのフェイルオーバーが発生した場合は、新しいマスターの接続先を回答するようになります

Redis Sentinelは、複数のプロセスが協調動作するように設計されています。

マスター障害検出に対しては、複数のSentinelプロセスの同意を必要とします。また、Sentinelプロセスが複数あることで、Sentinelが単一障害点になることを回避します。

なお、SentinelはRedisの起動モードが変わったようなものなので、結局のところ、Redis Sentinelを稼働させるには最低5つのRedisが必要だ、ということになります。

Sentinelプロセスが3つを下回った場合の問題点は、以下を参照してください。

[Example 1: just two Sentinels, DON'T DO THIS](https://redis.io/topics/sentinel#example-1-just-two-sentinels-don39t-do-this)

また、ネットワーク分断時に、孤立したマスターへの書き込みを停止する場合は、以下の構成例を参考にするとよいでしょう。

[Example 2: basic setup with three boxes](https://redis.io/topics/sentinel#example-2-basic-setup-with-three-boxes)

指定したスレーブ数への書き込みができなくなった場合、マスターへの書き込みを停止する、というやり方ですね。

```
min-slaves-to-write 1
min-slaves-max-lag 10
```

Redis Sentinel自体の設定については、以下を見るとよいでしょう。

[The self documented redis-sentinel.conf for Redis 5.0](https://raw.githubusercontent.com/antirez/redis/5.0/sentinel.conf)

どちらにせよ、Redis Sentinelとはマスター障害時のフェイルオーバーが可能なRedisソリューションです。

これに加えてスケーラビリティも欲しい、ということであれば、Redis Clusterを検討しましょう。さらに必要なプロセス数が増えますけど。

とまあ、いろいろ書きましたが、とりあえず動かしてみましょう。

今回は、

* Redis Sentinelを構成する
* マスターをダウンさせて、フェイルオーバーさせてみる
* 手動でフェイルオーバー（スイッチオーバー）させてみる

ということをやってみたいと思います。


# 環境

今回の確認環境。

```shell
$ cat /etc/redhat-release 
CentOS Linux release 7.6.1810 (Core) 


$ uname -a
Linux localhost.localdomain 3.10.0-957.12.2.el7.x86_64 #1 SMP Tue May 14 21:24:32 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux


$ redis-server -v
Redis server v=5.0.5 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=619d60bfb0a92c36


$ redis-sentinel -v
Redis server v=5.0.5 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=619d60bfb0a92c36
```

Redis 5.0.5です。

サーバーは5台用意し、それぞれ以下とします。

* マスター … `192.168.33.10`
* レプリカ … `192.168.33.11`
* Sentinel 1〜3 … `192.168.33.12`〜`194.168.33.14`

ちなみに、`redis-sentinel`というコマンドは、以下のようになっています。

```shell
$ ll /usr/bin/redis-sentinel 
lrwxrwxrwx. 1 root root 12 Sep 20 11:30 /usr/bin/redis-sentinel -> redis-server
```


# CentOSへRedisをインストールする

Remi Repositoryから、可能な限り新しいRedisをインストールします。

```shell
$ sudo yum install epel-release
$ sudo yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
$ sudo yum --enablerepo=remi install redis
```


# レプリケーションを構成する

最初に、レプリケーションを構成しましょう。

Remi Repositoryからインストールした、Redisのデフォルトの設定はこちら。設定ファイルは、`/etc/redis.conf`です。

```shell
$ sudo grep -v '#' /etc/redis.conf | grep -v '^$'
bind 127.0.0.1
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis/redis.log
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
```

マスター側は、`bind`のみ変更します。

```shell
bind 0.0.0.0
```

レプリカ側は、`bind`および`replicaof`を設定します。

```shell
bind 0.0.0.0

replicaof 192.168.33.10 6379
```

マスター、レプリカ両方で、Redisを起動します。

```shell
$ sudo systemctl start redis
```

確認しましょう。

マスターに接続。

```shell
$ redis-cli -h 192.168.33.10
```

レプリケーションの情報確認。

```shell
192.168.33.10:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.33.11,port=6379,state=online,offset=56,lag=1
master_replid:aff8286a42ef1093f17e446a98d94eac153a9111
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:56
```

データの登録。

```shell
192.168.33.10:6379> set key1 value1
OK
192.168.33.10:6379> set key2 value2
OK
```

続いて、レプリカへ接続。

```shell
$ redis-cli -h 192.168.33.11
```

レプリケーションの情報確認。

```shell
192.168.33.11:6379> info replication
# Replication
role:slave
master_host:192.168.33.10
master_port:6379
master_link_status:up
master_last_io_seconds_ago:6
master_sync_in_progress:0
slave_repl_offset:261
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:aff8286a42ef1093f17e446a98d94eac153a9111
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:261
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:261
```

レプリケーションしたエントリが取得できることを確認します。

```shell
192.168.33.11:6379> get key1
"value1"
192.168.33.11:6379> get key2
"value2"
```

また、Read-Onlyのレプリカであるので、データの更新はできません。

```shell
192.168.33.11:6379> set key3 value3
(error) READONLY You can't write against a read only replica.
```


# Redis Sentinelを構成する

では、Redis Sentinelを構成してみましょう。

まずは、Remi Repositoryでインストールした、デフォルトのSentinelの設定を確認してみます。

```shell
$ sudo grep -v '#' /etc/redis-sentinel.conf | grep -v '^$'
port 26379
daemonize no
pidfile /var/run/redis-sentinel.pid
logfile /var/log/redis/sentinel.log
dir /tmp
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
```

Sentinelプロセスは、`26379`ポートを使うようです。

```shell
port 26379
```

設定としては、今回は`sentinel monitor`を変更します。

```shell
sentinel monitor mymaster 192.168.33.10 6379 2
```

Redis Sentinelにおいて重要なのは、このあたりですね。

```shell
sentinel monitor mymaster 192.168.33.10 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
```

まずは、`sentinel monitor`から。以下のような構文になります。

```shell
sentinel monitor <master-name> <ip> <port> <quorum>
```

`<master-name>`が監視するマスター名で、その後ろにマスターの接続先アドレス、ポートを指定します。

QUORUMは、マスターに障害があったと判定するために必要な、Sentinelのプロセス数を指定します。

例えば、以下の設定だと`192.168.33.10:6379`に対して、2つのSentinelプロセスが同意すれば、フェイルオーバーが始まります。

```shell
sentinel monitor mymaster 192.168.33.10 6379 2
```

3つのSentinelプロセスが同意した場合もフェイルオーバーが始まりますが、同意したSentinelプロセスがひとつの場合はフェイルオーバーが始まりません。

これは、Sentinelプロセスがネットワーク分断された時に、Sentinelを構成するプロセスが細かく分断されるなど、大部分のプロセスが通信できない状態に陥った時には、フェイルオーバーが行われないことを意味します。

ところで、レプリカに関する設定がありませんが、レプリカはSentinelが検出するようです。

その他のオプションは、以下の構文に沿って記載されます。

```shell
sentinel <option_name> <master_name> <option_value>
```

`down-after-milliseconds`は、Sentinelがマスターがダウンしたと判定し始めるまでの時間（ミリ秒）です。デフォルトでは、判定まで30秒かかることになります。

`parallel-syncs`は、フェイルオーバー中に、新しいレプリカを並列に再構成する数です。数値が小さいほど、フェールオーバープロセスの完了に時間がかかるようになりますが、新しいマスターとの再同期中に、レプリカの大多数へ到達できなくなるような事態を避けることができるかもしれません。

`failover-timeout`は、フェイルオーバーのタイムアウトをミリ秒で指定します。

その他、`notification-script`でイベントに応じてスクリプトを実行したり、マスター変更時に`client-reconfig-script`でスクリプトを実行したりできます。

`deny-scripts-reconfig`は、`SENTINEL SET`コマンドで、スクリプトを変更できるかどうかです。これは、セキュリティに関する設定ですね。

とりあえず、最低限構成したので、Sentinelプロセスを起動してみましょう。

```shell
$ sudo systemctl start redis-sentinel
```

確認。Sentinelのうち、ひとつに接続してみます。Sentinelの`26379`に接続しているところがポイントですね。

```shell
$ redis-cli -h 192.168.33.12 -p 26379
```

Sentinelから見た、マスターの情報。

```shell
192.168.33.12:26379> sentinel masters
1)  1) "name"
    2) "mymaster"
    3) "ip"
    4) "192.168.33.10"
    5) "port"
    6) "6379"
    7) "runid"
    8) "332fb485b939a0169cc5066ba07892833948bd7d"
    9) "flags"
   10) "master"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "376"
   19) "last-ping-reply"
   20) "376"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "7648"
   25) "role-reported"
   26) "master"
   27) "role-reported-time"
   28) "328836"
   29) "config-epoch"
   30) "0"
   31) "num-slaves"
   32) "1"
   33) "num-other-sentinels"
   34) "2"
   35) "quorum"
   36) "2"
   37) "failover-timeout"
   38) "180000"
   39) "parallel-syncs"
   40) "1"
```

Sentinelから見た、レプリカの情報。

```shell
192.168.33.12:26379> sentinel replicas mymaster
1)  1) "name"
    2) "192.168.33.11:6379"
    3) "ip"
    4) "192.168.33.11"
    5) "port"
    6) "6379"
    7) "runid"
    8) "d271c03507463746ae65e6a0ff24e101f5cd5705"
    9) "flags"
   10) "slave"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "507"
   19) "last-ping-reply"
   20) "507"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "7775"
   25) "role-reported"
   26) "slave"
   27) "role-reported-time"
   28) "379083"
   29) "master-link-down-time"
   30) "0"
   31) "master-link-status"
   32) "ok"
   33) "master-host"
   34) "192.168.33.10"
   35) "master-port"
   36) "6379"
   37) "slave-priority"
   38) "100"
   39) "slave-repl-offset"
   40) "77172"
```

Sentinel自体の情報。

```shell
192.168.33.12:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.33.10:6379,slaves=1,sentinels=3
```

マスターおよびレプリカのRedisは、ふつうに使い続けられます。

これらRedis Sentinelのコマンドは、以下に記載があります。

[Sentinel commands](https://redis.io/topics/sentinel#sentinel-commands)


# マスターをダウンさせてみる

それではここで、マスターをダウンさせてみます。

```shell
$ sudo systemctl stop redis
```

Sentinelプロセスに接続して、しばらく待ちます。

```shell
$ redis-cli -h 192.168.33.12 -p 26379
```

そのうち、マスターが切り替わります。

```shell
192.168.33.12:26379> sentinel masters
1)  1) "name"
    2) "mymaster"
    3) "ip"
    4) "192.168.33.11"
    5) "port"
    6) "6379"
    7) "runid"
    8) "d271c03507463746ae65e6a0ff24e101f5cd5705"
    9) "flags"
   10) "master"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "43"
   19) "last-ping-reply"
   20) "43"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "784"
   25) "role-reported"
   26) "master"
   27) "role-reported-time"
   28) "21844"
   29) "config-epoch"
   30) "1"
   31) "num-slaves"
   32) "1"
   33) "num-other-sentinels"
   34) "2"
   35) "quorum"
   36) "2"
   37) "failover-timeout"
   38) "180000"
   39) "parallel-syncs"
   40) "1"
```

マスターダウンを検出するまでの時間は、`down-after-milliseconds`を調整しましょう。

Sentinel構築時に見ていた時は、こうでした。

```shell
192.168.33.12:26379> sentinel masters
1)  1) "name"
    2) "mymaster"
    3) "ip"
    4) "192.168.33.10"
```

レプリカがマスターに昇格しましたね。

Sentinelのログを見ると、マスターが切り替わったようなログが出力されています。

```
5312:S 24 Sep 2019 11:24:25.754 * Connecting to MASTER 192.168.33.10:6379
5312:S 24 Sep 2019 11:24:25.754 * MASTER <-> REPLICA sync started
5312:S 24 Sep 2019 11:24:25.754 # Error condition on socket for SYNC: Connection refused
5312:S 24 Sep 2019 11:24:26.764 * Connecting to MASTER 192.168.33.10:6379
5312:S 24 Sep 2019 11:24:26.764 * MASTER <-> REPLICA sync started
5312:S 24 Sep 2019 11:24:26.764 # Error condition on socket for SYNC: Connection refused
5312:M 24 Sep 2019 11:24:27.465 # Setting secondary replication ID to aff8286a42ef1093f17e446a98d94eac153a9111, valid up to offset: 71573345. New replication ID is 9cf18954c304305a2cd2021ba7c5edfd3fa1d89f
5312:M 24 Sep 2019 11:24:27.465 * Discarding previously cached master state.
5312:M 24 Sep 2019 11:24:27.465 * MASTER MODE enabled (user request from 'id=5 addr=192.168.33.12:50972 fd=8 name=sentinel-b3877526-cmd age=342869 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=140 qbuf-free=32628 obl=36 oll=0 omem=0 events=r cmd=exec')
```

ここで、新しいマスターに接続してみます。

```shell
$ redis-cli -h 192.168.33.11
```

既存の値は取得できます。

```shell
192.168.33.11:6379> get key1
"value1"
192.168.33.11:6379> get key2
"value2"
```

そして今度は、更新ができるようになります。

```shell_session
192.168.33.11:6379> set key3 value3
OK
```

マスターになったので、書き込みができるようになった、ということですね。

そういえば、Sentinel上のレプリカの情報はどうなったんでしょう。Sentinelに接続してみます。

```shell
$ redis-cli -h 192.168.33.12 -p 26379
```

レプリカの情報を見てみます。

```shell
192.168.33.12:26379> sentinel replicas mymaster
1)  1) "name"
    2) "192.168.33.10:6379"
    3) "ip"
    4) "192.168.33.10"
    5) "port"
    6) "6379"
    7) "runid"
    8) ""
    9) "flags"
   10) "s_down,slave,disconnected"
   11) "link-pending-commands"
   12) "3"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "290187"
   17) "last-ok-ping-reply"
   18) "290187"
   19) "last-ping-reply"
   20) "290187"
   21) "s-down-time"
   22) "260131"
   23) "down-after-milliseconds"
   24) "30000"
   25) "info-refresh"
   26) "1569324559147"
   27) "role-reported"
   28) "slave"
   29) "role-reported-time"
   30) "290187"
   31) "master-link-down-time"
   32) "0"
   33) "master-link-status"
   34) "err"
   35) "master-host"
   36) "?"
   37) "master-port"
   38) "0"
   39) "slave-priority"
   40) "100"
   41) "slave-repl-offset"
   42) "0"
```

ダウンしてしまったマスターの情報が見えますね。というか、設定に`replicaof`とは書いていないわけですが…。

ではここで、停止していた古いマスターを起動してみましょう。

```shell
$ sudo systemctl start redis
```

マスターの情報を見てみます。

```shell
192.168.33.12:26379> sentinel masters
1)  1) "name"
    2) "mymaster"
    3) "ip"
    4) "192.168.33.11"
    5) "port"
    6) "6379"
    7) "runid"
    8) "d271c03507463746ae65e6a0ff24e101f5cd5705"
    9) "flags"
   10) "master"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "439"
   19) "last-ping-reply"
   20) "439"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "7578"
   25) "role-reported"
   26) "master"
   27) "role-reported-time"
   28) "420131"
   29) "config-epoch"
   30) "1"
   31) "num-slaves"
   32) "1"
   33) "num-other-sentinels"
   34) "2"
   35) "quorum"
   36) "2"
   37) "failover-timeout"
   38) "180000"
   39) "parallel-syncs"
   40) "1"
```

変わらず、新しいマスターのままです。

レプリカの情報を見てみます。

```shell
192.168.33.12:26379> sentinel replicas mymaster
1)  1) "name"
    2) "192.168.33.10:6379"
    3) "ip"
    4) "192.168.33.10"
    5) "port"
    6) "6379"
    7) "runid"
    8) "fd110d0a511c9d97fb447931869b5419ba74167b"
    9) "flags"
   10) "slave"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "544"
   19) "last-ping-reply"
   20) "544"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "7916"
   25) "role-reported"
   26) "slave"
   27) "role-reported-time"
   28) "79179"
   29) "master-link-down-time"
   30) "0"
   31) "master-link-status"
   32) "ok"
   33) "master-host"
   34) "192.168.33.11"
   35) "master-port"
   36) "6379"
   37) "slave-priority"
   38) "100"
   39) "slave-repl-offset"
   40) "71670531"
```

こちらは、旧マスターですね。`replicaof`を書いていないのに、レプリカになりました…。

新しいマスターに接続して、値を確認。

```shell
$ redis-cli -h 192.168.33.11
192.168.33.11:6379> get key1
"value1"
192.168.33.11:6379> get key2
"value2"
192.168.33.11:6379> get key3
"value3"
```

再起動させた、旧マスターで確認。

```shell
$ redis-cli -h 192.168.33.10
192.168.33.10:6379> get key1
"value1"
192.168.33.10:6379> get key2
"value2"
192.168.33.10:6379> get key3
"value3"
```

新しいマスターで登録した値も見えています。

なお、こちらはレプリカに切り替わっているので、Read-Onlyになります。

```shell
192.168.33.10:6379> set key4 value4
(error) READONLY You can't write against a read only replica.
```

これで、マスター障害時のレプリカ昇格と、停止していたマスターが復旧した時にどうなるかが確認できましたね。

ちなみに、停止していたマスターが起動した場合のSentinelのログはこんな感じでした。

```shell
5312:M 24 Sep 2019 11:31:04.493 * Replica 192.168.33.10:6379 asks for synchronization
5312:M 24 Sep 2019 11:31:04.493 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'a0ba3e978e869392308838fad47bf36967d57f34', my replication IDs are '9cf18954c304305a2cd2021ba7c5edfd3fa1d89f' and 'aff8286a42ef1093f17e446a98d94eac153a9111')
5312:M 24 Sep 2019 11:31:04.493 * Starting BGSAVE for SYNC with target: disk
5312:M 24 Sep 2019 11:31:04.493 * Background saving started by pid 26297
26297:C 24 Sep 2019 11:31:04.494 * DB saved on disk
26297:C 24 Sep 2019 11:31:04.495 * RDB: 0 MB of memory used by copy-on-write
5312:M 24 Sep 2019 11:31:04.538 * Background saving terminated with success
5312:M 24 Sep 2019 11:31:04.538 * Synchronization with replica 192.168.33.10:6379 succeeded
```

# 手動でフェイルオーバーする
最後に、手動でフェイルオーバー（スイッチオーバー）してみましょう。`sentinel failover`コマンドで実行できます。

```shell
sentinel failover <master name>
```

ここまでで、最初に作った時からマスターとレプリカが入れ替わっているので、切り替えてみます。

```shell
$ redis-cli -h 192.168.33.12 -p 26379
192.168.33.12:26379> sentinel failover mymaster
OK
```

マスターの情報。

```shell
192.168.33.12:26379> sentinel masters
1)  1) "name"
    2) "mymaster"
    3) "ip"
    4) "192.168.33.10"
    5) "port"
    6) "6379"
    7) "runid"
    8) ""
    9) "flags"
   10) "master"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "242"
   19) "last-ping-reply"
   20) "242"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "9364"
   25) "role-reported"
   26) "master"
   27) "role-reported-time"
   28) "6612"
   29) "config-epoch"
   30) "2"
   31) "num-slaves"
   32) "1"
   33) "num-other-sentinels"
   34) "2"
   35) "quorum"
   36) "2"
   37) "failover-timeout"
   38) "180000"
   39) "parallel-syncs"
   40) "1"
```

レプリカの情報。

```shell
192.168.33.12:26379> sentinel replicas mymaster
1)  1) "name"
    2) "192.168.33.11:6379"
    3) "ip"
    4) "192.168.33.11"
    5) "port"
    6) "6379"
    7) "runid"
    8) "d271c03507463746ae65e6a0ff24e101f5cd5705"
    9) "flags"
   10) "slave"
   11) "link-pending-commands"
   12) "0"
   13) "link-refcount"
   14) "1"
   15) "last-ping-sent"
   16) "0"
   17) "last-ok-ping-reply"
   18) "599"
   19) "last-ping-reply"
   20) "599"
   21) "down-after-milliseconds"
   22) "30000"
   23) "info-refresh"
   24) "1960"
   25) "role-reported"
   26) "slave"
   27) "role-reported-time"
   28) "43112"
   29) "master-link-down-time"
   30) "0"
   31) "master-link-status"
   32) "ok"
   33) "master-host"
   34) "192.168.33.10"
   35) "master-port"
   36) "6379"
   37) "slave-priority"
   38) "100"
   39) "slave-repl-offset"
   40) "71779565"
```

切り替わりましたね。

先程までマスターになっていた方が、Read-Onlyなレプリカになっています。

```shell
$ redis-cli -h 192.168.33.11
192.168.33.11:6379> set key4 value4
(error) READONLY You can't write against a read only replica.
```

マスターで更新。

```shell
$ redis-cli -h 192.168.33.10
192.168.33.10:6379> set key4 value4
OK
```

レプリカで確認。

```shell
$ redis-cli -h 192.168.33.11
192.168.33.11:6379> get key4
"value4"
```

更新の確認もできました。

基本的な確認としては、こんなところでしょうか。