Carpe Diem

備忘録

Redis Clusterを冗長構成で構築

概要

前回はマスターのみでRedis Clusterを構築しました。

christina04.hatenablog.com

今回は冗長構成で構築し、可用性を確認します。

環境

  • Redis 5.0.7

Replicationを含めた冗長構成

各シャード1台ずつReplicationを用意して冗長構成にしてみます。

システム図

イメージはこちら

f:id:quoll00:20200401013045p:plain

設定

docker-compose.yaml

6台起動させます。

version: '3'

services:
  node_1: &base
    image: redis:alpine
    volumes:
      - $PWD/redis.conf:/usr/local/etc/redis/redis.conf
    command: redis-server /usr/local/etc/redis/redis.conf
    networks:
      - redis_net
  node_2:
    <<: *base
  node_3:
    <<: *base
  node_4:
    <<: *base
  node_5:
    <<: *base
  node_6:
    <<: *base

networks:
  redis_net:
    driver: bridge
    ipam:
     driver: default
     config:
       - subnet: 172.30.0.0/24

cluster構築

起動できたらその内1台に入ります。

$ docker exec -it cluster_node_1_1 /bin/ash

そしてcluster構築コマンドを実行します。
今回は--cluster-replicasオプションを付けます。

data# redis-cli --cluster create \
  172.30.0.2:6379 172.30.0.3:6379 \
  172.30.0.4:6379 172.30.0.5:6379 \
  172.30.0.6:6379 172.30.0.7:6379 \
  --cluster-replicas 1

--cluster-replicas 1とするとマスター毎に1つのreplicaを追加します。
また前回同様自動でhash slotsを配分してくれます。

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.30.0.6:6379 to 172.30.0.2:6379
Adding replica 172.30.0.7:6379 to 172.30.0.3:6379
Adding replica 172.30.0.5:6379 to 172.30.0.4:6379
M: 0c4f3f7417cd2adb374f4ef9999171c909bd31f6 172.30.0.2:6379
   slots:[0-5460] (5461 slots) master
M: e8fb2156906daefe3dc09adac242cb53bee14d54 172.30.0.3:6379
   slots:[5461-10922] (5462 slots) master
M: 69815efc30606972f6fb02d931f135e86091065a 172.30.0.4:6379
   slots:[10923-16383] (5461 slots) master
S: 1e3727c7adfef0b11f7f85dbe60db16fabb5b45c 172.30.0.5:6379
   replicates 69815efc30606972f6fb02d931f135e86091065a
S: 35d8403388b5d1d161eb585875070c3a3d7528d6 172.30.0.6:6379
   replicates 0c4f3f7417cd2adb374f4ef9999171c909bd31f6
S: 5454de425f533ab1693be1f700e0798f551dec30 172.30.0.7:6379
   replicates e8fb2156906daefe3dc09adac242cb53bee14d54
Can I set the above configuration? (type 'yes' to accept):

上記設定で問題なければyesを入力。

>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 172.30.0.2:6379)
M: 0c4f3f7417cd2adb374f4ef9999171c909bd31f6 172.30.0.2:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 5454de425f533ab1693be1f700e0798f551dec30 172.30.0.7:6379
   slots: (0 slots) slave
   replicates e8fb2156906daefe3dc09adac242cb53bee14d54
S: 35d8403388b5d1d161eb585875070c3a3d7528d6 172.30.0.6:6379
   slots: (0 slots) slave
   replicates 0c4f3f7417cd2adb374f4ef9999171c909bd31f6
S: 1e3727c7adfef0b11f7f85dbe60db16fabb5b45c 172.30.0.5:6379
   slots: (0 slots) slave
   replicates 69815efc30606972f6fb02d931f135e86091065a
M: 69815efc30606972f6fb02d931f135e86091065a 172.30.0.4:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: e8fb2156906daefe3dc09adac242cb53bee14d54 172.30.0.3:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

作成できました。

/data # redis-cli --cluster info 172.30.0.2:6379
172.30.0.2:6379 (0c4f3f74...) -> 0 keys | 5461 slots | 1 slaves.
172.30.0.4:6379 (69815efc...) -> 0 keys | 5461 slots | 1 slaves.
172.30.0.3:6379 (e8fb2156...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.

前回と違って1 slavesになっていますね。

Failover

replicaがいるため、仮にmasterが死んだとしても

f:id:quoll00:20200401032441p:plain

Redis Clusterでは以下のようにreplicaがmasterへ昇格します。

f:id:quoll00:20200401032558p:plain

この挙動を検証してみます。

検証

検証のため適当にデータを入れておきます。

/data # redis-cli -c
127.0.0.1:6379> set 1 1
-> Redirected to slot [9842] located at 172.30.0.3:6379
OK
172.30.0.3:6379> set 2 2
OK
172.30.0.3:6379> set 3 3
-> Redirected to slot [1584] located at 172.30.0.2:6379
OK
172.30.0.2:6379> set 4 4
-> Redirected to slot [14039] located at 172.30.0.4:6379
OK
172.30.0.4:6379> set 5 5
-> Redirected to slot [9974] located at 172.30.0.3:6379
OK
172.30.0.3:6379> set 6 6
OK
172.30.0.3:6379>
/data # redis-cli --cluster info 172.30.0.2:6379
172.30.0.2:6379 (0c4f3f74...) -> 1 keys | 5461 slots | 1 slaves.
172.30.0.4:6379 (69815efc...) -> 1 keys | 5461 slots | 1 slaves.
172.30.0.3:6379 (e8fb2156...) -> 4 keys | 5462 slots | 1 slaves.
[OK] 6 keys in 3 masters.

172.30.0.2のコンテナをstopさせます。

$ docker stop cluster_node_2_1

するとredisのログでは以下のように昇格のための選出が行われます。今回node_6_1(172.30.0.6)が勝ったようです。

node_6_1  | 1:S 31 Mar 2020 18:32:42.850 # Starting a failover election for epoch 8.
node_4_1  | 1:M 31 Mar 2020 18:32:42.854 # Failover auth granted to 35d8403388b5d1d161eb585875070c3a3d7528d6 for epoch 8
node_5_1  | 1:M 31 Mar 2020 18:32:42.854 # Failover auth granted to 35d8403388b5d1d161eb585875070c3a3d7528d6 for epoch 8
node_6_1  | 1:S 31 Mar 2020 18:32:42.856 # Failover election won: I'm the new master.

クラスタの状態を確認します。

# redis-cli --cluster info 172.30.0.3:6379
Could not connect to Redis at 172.30.0.2:6379: Host is unreachable
172.30.0.3:6379 (e8fb2156...) -> 4 keys | 5462 slots | 1 slaves.
172.30.0.4:6379 (69815efc...) -> 1 keys | 5461 slots | 1 slaves.
172.30.0.6:6379 (35d84033...) -> 1 keys | 5461 slots | 0 slaves.
[OK] 6 keys in 3 masters.

172.30.0.2が死んだので、replicaだった172.30.0.6がmasterに昇格しています。

データ操作

replicaだった172.30.0.6にも書き込みができることを確認できます。

172.30.0.3:6379> set 3 3
-> Redirected to slot [1584] located at 172.30.0.6:6379
OK

落としたコンテナを起動してみる

172.30.0.2を起動してみます。

/data # redis-cli --cluster info 172.30.0.3:6379
172.30.0.3:6379 (e8fb2156...) -> 4 keys | 5462 slots | 1 slaves.
172.30.0.4:6379 (69815efc...) -> 1 keys | 5461 slots | 1 slaves.
172.30.0.6:6379 (35d84033...) -> 1 keys | 5461 slots | 1 slaves.
[OK] 6 keys in 3 masters.

すると今度は172.30.0.2172.30.0.6のreplicaに代わりました。
自動でfail backはしないようです。

許容できるダウン台数

failoverの図を見て分かるように、シャードにノードが残っているかが重要です。

まだOK

各シャード内でそれぞれ最低1台残っていれば稼働できます。

f:id:quoll00:20200401100828p:plain

アウト

しかしシャード内の全ノードが死んだ場合はRedis Clusterはサービス不能になります。

f:id:quoll00:20200401035539p:plain

Shard 0のノードを全て落としてみると

node_4_1  | 1:M 01 Apr 2020 01:04:39.599 # Cluster state changed: fail
node_3_1  | 1:S 01 Apr 2020 01:04:39.599 * Marking node 35d8403388b5d1d161eb585875070c3a3d7528d6 as failing (quorum reached).
node_3_1  | 1:S 01 Apr 2020 01:04:39.599 # Cluster state changed: fail
node_1_1  | 1:S 01 Apr 2020 01:04:39.600 * Marking node 35d8403388b5d1d161eb585875070c3a3d7528d6 as failing (quorum reached).
node_1_1  | 1:S 01 Apr 2020 01:04:39.600 # Cluster state changed: fail
node_5_1  | 1:M 01 Apr 2020 01:04:39.600 * Marking node 35d8403388b5d1d161eb585875070c3a3d7528d6 as failing (quorum reached).
node_5_1  | 1:M 01 Apr 2020 01:04:39.600 # Cluster state changed: fail

redisログ上では各ノードのCluster stateがfailに変わります。

そうなるとcluster infoは取れますが

/data # redis-cli --cluster info 172.30.0.3:6379
Could not connect to Redis at 172.30.0.2:6379: Host is unreachable
Could not connect to Redis at 172.30.0.6:6379: Host is unreachable
172.30.0.3:6379 (e8fb2156...) -> 4 keys | 5462 slots | 1 slaves.
172.30.0.4:6379 (69815efc...) -> 1 keys | 5461 slots | 1 slaves.
[OK] 5 keys in 2 masters.

データ操作しようとしてもできません。

/data # redis-cli -c
127.0.0.1:6379> get 1
(error) CLUSTERDOWN The cluster is down
127.0.0.1:6379> get 2
(error) CLUSTERDOWN The cluster is down
127.0.0.1:6379> get 3
(error) CLUSTERDOWN The cluster is down

Cluster down後にmasterが復帰した場合

上記の検証でダウンさせたShard 0のノードを復帰させてみます。

$ docker start cluster_node_6_1
cluster_node_6_1

復帰したノードはそのままmasterとなります。

/data # redis-cli --cluster info 172.30.0.3:6379
172.30.0.3:6379 (e8fb2156...) -> 4 keys | 5462 slots | 1 slaves.
172.30.0.4:6379 (69815efc...) -> 1 keys | 5461 slots | 1 slaves.
172.30.0.2:6379 (35d84033...) -> 1 keys | 5461 slots | 0 slaves.
[OK] 6 keys in 3 masters.

redisログを見ると各ノードのCluster stateはokに変わり、

node_4_1  | 1:M 01 Apr 2020 01:11:06.037 # Cluster state changed: ok
node_1_1  | 1:S 01 Apr 2020 01:11:06.037 * Clear FAIL state for node 35d8403388b5d1d161eb585875070c3a3d7528d6: is reachable again and nobody is serving its slots after some time.
node_1_1  | 1:S 01 Apr 2020 01:11:06.037 # Cluster state changed: ok
node_3_1  | 1:S 01 Apr 2020 01:11:06.037 * Clear FAIL state for node 35d8403388b5d1d161eb585875070c3a3d7528d6: is reachable again and nobody is serving its slots after some time.
node_3_1  | 1:S 01 Apr 2020 01:11:06.037 # Cluster state changed: ok
node_5_1  | 1:M 01 Apr 2020 01:11:06.037 * Clear FAIL state for node 35d8403388b5d1d161eb585875070c3a3d7528d6: is reachable again and nobody is serving its slots after some time.
node_5_1  | 1:M 01 Apr 2020 01:11:06.037 # Cluster state changed: ok
node_6_1  | 1:M 01 Apr 2020 01:11:07.993 # Cluster state changed: ok

データ操作も可能になります。

/data # redis-cli -c
127.0.0.1:6379> get 1
-> Redirected to slot [9842] located at 172.30.0.3:6379
"1"

まとめ

Redis Clusterを冗長構成で構築し、簡単なfailover検証をしてみました。

参考