Redisクラスタ構築とフェイルオーバー検証


はじめに

Redis-Clusterにおけるフェイルオーバー時の挙動について挙動検証を行ったので、検証時の備忘メモとして環境構築と検証結果メモを記す。

1. Redisクラスタ構築

1.1 Redisインストール

今回はMac環境で検証を行うため、homebrewなどでインストールを行う。
インストール方法はググれば出てくるので省略。

インストール後の起動確認として下記を実行する。

# Redisサーバをバックグラウンドで起動させる
# オプションを指定しない場合、デフォルトの「」が参照される
# デフォルトのポート番号は「6379」
$ redis-server --daemonize yes
# RedisCLIを起動させpingコマンドを実行し、PONGが返ってくるのを確認する
$ redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> exit
# Redisサーバの停止
$ redis-cli shutdown

1.2 Redis-Cluster構築と起動

Redis-Clusterを構築する場合、最低6台のマシンが必要となる。
今回は1台のマシンでクラスタを構築するため、別々のポート番号でRedisを起動しクラスタを構築する。
構築する際にデフォルト(Mac Homebrewインストールの場合)の/usr/local/etc/redis.confをコピーしredis-[ポート番号].confの名前で6ファイル作成し、/redis/conf/に配置し設定の追加・変更を行った。

  • ディレクトリ構成
/redis
  ├ log
  ├ conf
  ├ pid
  └ work
  • configファイルの設定内容
/redis/conf/redis-[ポート番号].conf
# Working Directory
dir /redis/work/
# ポート番号(今回だと7000~7005をそれぞれに設定する)
port XXXX
# PIDファイル
pidfile /redis/work/pid/redis-[ポート番号].pid
# ログファイル
logfile "/redis/log/redis-[ポート番号].log"
# DBファイル
dbfilename dump-[ポート番号].rdb
# AOFモードOn/Off設定
appendonly yes
# AppendOnlyFile
appendfilename "appendonly-[ポート番号].aof"
# クラスターモードOn/Off設定
cluster-enabled yes
# クラスター設定ファイル名
cluster-config-file cluster-config-[ポート番号].conf
# ReidsClusterのnode間通信におけるタイムアウト設定 (ミリ秒)
cluster-node-timeout=1000

ファイル作成後、6台のRedisを起動させ、redis-cliのコマンドでクラスタを構築する。
Redis-Clusterの構築方法はredis-cli--cluster createコマンドやredis-trib.rbを利用した方法※などがある。
redis-trib.rbはRedis3.0以降から利用可能であり、redis-trib.rbを使うのが一般的だが今回はフェイルオーバー検証が目的のため簡単に作れる--cluster createによりクラスタを構築する。

# 作成した6ファイルを指定し、Redisサーバを6台起動させる
$ redis-server /redis/conf/redis-7000.conf --daemonize yes
$ redis-server /redis/conf/redis-7001.conf --daemonize yes
$ redis-server /redis/conf/redis-7002.conf --daemonize yes
$ redis-server /redis/conf/redis-7003.conf --daemonize yes
$ redis-server /redis/conf/redis-7004.conf --daemonize yes
$ redis-server /redis/conf/redis-7005.conf --daemonize yes
# Redis-Clusterの構築
$ redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
# クラスタ作成時の標準出力は省略

クラスタの状態を確認し、master3台、slave3台が起動していればOK。
-cluster createコマンドでクラスタを構成した場合、Master/Slaveノードの割り振りはランダムで設定される
今回の場合は、下記構成でクラスターが構成された。

# クラスタ構成の場合-pオプションで接続先ポートを指定しないと接続エラーとなるので接続先ポートを指定する
$ redis-cli -p 7000 cluster nodes
dd5f9cd86a1758e6d88a5e5d2496f8f295cfccbf 127.0.0.1:7001@17001 master - 0 1605445940617 2 connected 5461-10922
bb439ff10930780ad6cbd11a72136728f718dcf9 127.0.0.1:7000@17000 myself,master - 0 1605445940000 1 connected 0-5460
5a3976ef7bf2656714cbbd54d9f42e5da5c8747c 127.0.0.1:7005@17005 slave dd5f9cd86a1758e6d88a5e5d2496f8f295cfccbf 0 1605445940822 2 connected
09fbbd23ec43cb1189319c819111fbbf57f080cf 127.0.0.1:7003@17003 slave 130464b52347bb3ac76c090ec6ca7a4232451d65 0 1605445940822 3 connected
d2fd5916251ac934ede4a32d95e8c68cae741a42 127.0.0.1:7004@17004 slave bb439ff10930780ad6cbd11a72136728f718dcf9 0 1605445940617 1 connected
130464b52347bb3ac76c090ec6ca7a4232451d65 127.0.0.1:7002@17002 master - 0 1605445940720 3 connected 10923-16383

2. Redis-Clusterのフェイルオーバー検証

2.1 Masterノードの異常

Redis-Clusterのmasterに障害等が発生した場合、障害を検知しフェイルオーバー(masterとslaveを切り替え)が発生する。
フェイルオーバーにかかる時間はredis.confcluster-node-timeoutパラメータの設定値に依存している。
各ノードのcluster-node-timeoutを1秒、15秒、30秒に設定した状況で、擬似的な障害を発生させフェイルオーバーによるMaster/Slaveの切り替え完了までにかかる時間の計測を行った。

redis-clicluster nodesコマンドを1秒間隔で実行することで切り替え時間の計測を、擬似的な障害はでMasterノードのプロセスを落とすことで発生させた。

計測結果は下表のとおりである。

cluster-node-timeoutの設定値 フェイルオーバー完了までの時間
1秒 3秒
15秒 21秒
30秒 35秒

cluster-node-timeout=15秒設定時におけるcluster nodesコマンドの実行結果は以下の通りであり、Masterプロセスのkillから約15秒後にMasterノードの以上を検知し、その4秒後にMaster/Slaveの切り替わりが完了している。

# ポート7000/7004以外のノード情報は省略
==========================================
== 22:57:44
# 22:57:44に7000ポートのノードのプロセスをkill
Kill Process redis-server 127.0.0.1:7000
==========================================
== 22:57:44
bb439ff10930780ad6cbd11a72136728f718dcf9 127.0.0.1:7000@17000 master - 0 1605448662626 8 disconnected 0-5460
d2fd5916251ac934ede4a32d95e8c68cae741a42 127.0.0.1:7004@17004 slave bb439ff10930780ad6cbd11a72136728f718dcf9 0 1605448664658 8 connected
==========================================
== 22:58:00
bb439ff10930780ad6cbd11a72136728f718dcf9 127.0.0.1:7000@17000 master - 1605448665679 1605448662626 8 disconnected 0-5460
d2fd5916251ac934ede4a32d95e8c68cae741a42 127.0.0.1:7004@17004 slave bb439ff10930780ad6cbd11a72136728f718dcf9 0 1605448680033 8 connected
==========================================
== 22:58:01
# 7000ポートのノードの状態が「fail?」に変化
bb439ff10930780ad6cbd11a72136728f718dcf9 127.0.0.1:7000@17000 master,fail? - 1605448665679 1605448662626 8 disconnected 0-5460
d2fd5916251ac934ede4a32d95e8c68cae741a42 127.0.0.1:7004@17004 slave bb439ff10930780ad6cbd11a72136728f718dcf9 0 1605448680033 8 connected
==========================================
== 22:58:04
# 7000ポートのノードの状態が「fail」に変化
bb439ff10930780ad6cbd11a72136728f718dcf9 127.0.0.1:7000@17000 master,fail - 1605448665679 1605448662626 8 disconnected 0-5460
d2fd5916251ac934ede4a32d95e8c68cae741a42 127.0.0.1:7004@17004 slave bb439ff10930780ad6cbd11a72136728f718dcf9 0 1605448684155 8 connected
==========================================
== 22:58:05
# ポート7000/7004のMaster/Slaveが切り替わる
bb439ff10930780ad6cbd11a72136728f718dcf9 127.0.0.1:7000@17000 master,fail - 1605448665679 1605448662626 8 disconnected
d2fd5916251ac934ede4a32d95e8c68cae741a42 127.0.0.1:7004@17004 master - 0 1605448684155 9 connected 0-5460
==========================================

2.2 failoverコマンドによる手動フェイルオーバー

RedisのMasterノード障害だけでなく、redis-cliのコマンドにて手動で強制的にフェイルオーバーを起こすことも可能である。
手動フェイルオーバーを起こす場合、Slaveノードのマシンに対して、フェイルオーバーコマンドを実行することでMasterとSlaveの切り替えが発生する。

# クラスターフェイルオーバーコマンド
$ redis-cluster -p <Slaveノードのポート番号> cluster failover

今回は、手動フェイルオーバーを実行してから実際にフェイルオーバーが完了(Master/Slaveの切り替わり)するまでにかかる時間の検証を行う。検証方法は「2. Redis-Clusterのフェイルオーバー検証」と同じく1秒間隔でredis-clicluster nodesコマンドを実行している状態で、culster failoverコマンドの実行するこでフェイルオーバーを発生させた。
検証結果は下記表のとおりで、cluster-node-timeoutび設定値にかかわらず、即時に切り替わることが確認できている。

cluster-node-timeoutの設定値 フェイルオーバー完了までの時間
1秒 1秒
15秒 1秒
30秒 1秒

検証におけるcluster nodesコマンドの実行結果は以下の通りであり、フェイルオーバーコマンド実行から1秒以内のMastertとSlave切り替わりが確認できた。

==========================================
== 22:36:18
# 22:36:18にredis-cliのフェイルオーバーコマンドを実行
Redis Command Failover Eexecute.
==========================================
== 22:36:18
bb439ff10930780ad6cbd11a72136728f718dcf9 127.0.0.1:7000@17000 master - 0 1605447378364 1 connected 0-5460
d2fd5916251ac934ede4a32d95e8c68cae741a42 127.0.0.1:7004@17004 slave bb439ff10930780ad6cbd11a72136728f718dcf9 0 1605447378159 1 connected
==========================================
== 22:36:19
# ポート7000/7004のMaster/Slaveが切り替わる
bb439ff10930780ad6cbd11a72136728f718dcf9 127.0.0.1:7000@17000 slave d2fd5916251ac934ede4a32d95e8c68cae741a42 0 1605447379388 7 connected
d2fd5916251ac934ede4a32d95e8c68cae741a42 127.0.0.1:7004@17004 master - 0 1605447379696 7 connected 0-5460
==========================================

2.3 結果まとめ

  • ノード障害発生時のフェイルオーバー完了までにかかる時間はcluster-node-timeoutの設定値に依存する。
  • cluster failoverによるフェイルオーバーは即時切り替わりであり、cluster-node-timeoutの設定値に依存しない。

参考資料