Redis Clusterを作ってみる
Redis Clusterの作成方法を確認してみます。
環境
- CentOS 8.1.1911
- Redis 6.0.3
クラスター構成
1台のCentOS上に、プロセスを分けて各Redisサーバーを起動します。
Redisサーバー種類 | Redis port | Cluster Port |
---|---|---|
Redis Master | 6379 | 16379 |
Redis Master | 6380 | 16380 |
Redis Master | 6381 | 16381 |
Redis Slave(Replica) | 6382 | 16382 |
Redis Slave(Replica) | 6383 | 16383 |
Redis Slave(Replica) | 6384 | 16384 |
基本的なRedisの設定は実施済みとして、作業を進めます。
作成
公式ドキュメントを参考に作業を進めます。
Cluster用パラメーター設定
公式ドキュメントとコンフィグ内の記載を参考に、必要パラメーターを設定します。
Redis Cluster configuration parameters
Redis configuration file example
こんな感じでしょうか。クラスターに参加する全Redisサーバーに設定します。
パラメーター名 | 値 |
---|---|
cluster-enabled | yes |
cluster-config-file | nodes-(redis port).conf |
cluster-node-timeout | 5000 |
cluster-replica-validity-factor | 10 |
repl-ping-replica-period | 10 |
cluster-migration-barrier | 1 |
cluster-require-full-coverage | yes |
cluster-replica-no-failover | no |
cluster-allow-reads-when-down | no |
appendonly | yes |
appendfilename | appendonly-(redis port).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 |
公式ドキュメントでは、Append Only Modeを有効とするように記載ありました。Append Only ModeとはAppend Only Fileを生成するModeとなっており、
The Append Only File, usually called simply AOF, is the main Redis persistence option. The way it works is extremely simple: every time a write operation that modifies the dataset in memory is performed, the operation gets logged. The log is produced exactly in the same format used by clients to communicate with Redis, so the AOF can be even piped via netcat to another instance, or easily parsed if needed. At restart Redis re-plays all the operations to reconstruct the dataset.
Relational Databaseにおけるアクティブログみたいなもの、という理解をしました。
Redisプロセスを起動すると、Clusterモードで起動されます。
$ ps -aef | grep redis | grep -v grep redis 832 1 0 12:30 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6379 [cluster] redis 838 1 0 12:30 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6384 [cluster] redis 839 1 0 12:30 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6380 [cluster] redis 840 1 0 12:30 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6382 [cluster] redis 841 1 0 12:30 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6381 [cluster] redis 842 1 0 12:30 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6383 [cluster]
Clusterの作成
パラメーターを設定してプロセスを起動しただけでは、RedisプロセスはClusterモードで起動しているのみで、実際にはCluster化されている訳ではありません。各RedisプロセスをCluster化するため、以下コマンドを実行します。
$ redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 127.0.0.1:6383 to 127.0.0.1:6379 Adding replica 127.0.0.1:6384 to 127.0.0.1:6380 Adding replica 127.0.0.1:6382 to 127.0.0.1:6381 >>> Trying to optimize slaves allocation for anti-affinity [WARNING] Some slaves are in the same host as their master M: 35180c311d8b46fd9b824878d0384de97131b181 127.0.0.1:6379 slots:[0-5460] (5461 slots) master M: 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb 127.0.0.1:6380 slots:[5461-10922] (5462 slots) master M: 3a97895f36a696893292160e73c31c35ac3f9ddb 127.0.0.1:6381 slots:[10923-16383] (5461 slots) master S: b3fa07636fc447b047f1ec18bb53d3b37697b807 127.0.0.1:6382 replicates 35180c311d8b46fd9b824878d0384de97131b181 S: 147be2a171022d5bdba3ca3a122cf1d3a29d7ab7 127.0.0.1:6383 replicates 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb S: e73b19a1f3e60eb74992baeb8c6e183904bd8573 127.0.0.1:6384 replicates 3a97895f36a696893292160e73c31c35ac3f9ddb 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 127.0.0.1:6379) M: 35180c311d8b46fd9b824878d0384de97131b181 127.0.0.1:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: e73b19a1f3e60eb74992baeb8c6e183904bd8573 127.0.0.1:6384 slots: (0 slots) slave replicates 3a97895f36a696893292160e73c31c35ac3f9ddb M: 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb 127.0.0.1:6380 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: b3fa07636fc447b047f1ec18bb53d3b37697b807 127.0.0.1:6382 slots: (0 slots) slave replicates 35180c311d8b46fd9b824878d0384de97131b181 M: 3a97895f36a696893292160e73c31c35ac3f9ddb 127.0.0.1:6381 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 147be2a171022d5bdba3ca3a122cf1d3a29d7ab7 127.0.0.1:6383 slots: (0 slots) slave replicates 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
masterが3台、slave(replica)が3台で、Clusterが作成されています。
$ redis-cli cluster nodes 35180c311d8b46fd9b824878d0384de97131b181 127.0.0.1:6379@16379 myself,master - 0 1591278326000 1 connected 0-5460 e73b19a1f3e60eb74992baeb8c6e183904bd8573 127.0.0.1:6384@16384 slave 3a97895f36a696893292160e73c31c35ac3f9ddb 0 1591278326825 6 connected 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb 127.0.0.1:6380@16380 master - 0 1591278327333 2 connected 5461-10922 b3fa07636fc447b047f1ec18bb53d3b37697b807 127.0.0.1:6382@16382 slave 35180c311d8b46fd9b824878d0384de97131b181 0 1591278327838 4 connected 3a97895f36a696893292160e73c31c35ac3f9ddb 127.0.0.1:6381@16381 master - 0 1591278326000 3 connected 10923-16383 147be2a171022d5bdba3ca3a122cf1d3a29d7ab7 127.0.0.1:6383@16383 slave 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb 0 1591278326000 5 connected
Redis Clusterでは、登録されるKey毎に各master nodeへshardingされて格納されます。sharding先となるmasterは、keyごとに計算されるhash値により決定し、各master nodeにて格納することになるhash値が割り当てられています。上記のコマンド結果では、各master nodeのレコード末尾の 0-5460
や 5461-10922
が、割り当てられているhash値となります。
The key space is split into 16384 slots, effectively setting an upper limit for the cluster size of 16384 master nodes (however the suggested max size of nodes is in the order of ~ 1000 nodes).
Each master node in a cluster handles a subset of the 16384 hash slots.
The base algorithm used to map keys to hash slots is the following (read the next paragraph for the hash tag exception to this rule):
HASH_SLOT = CRC16(key) mod 16384
hash値を求めるより詳細なアルゴリズムは、公式にドキュメントに記載されています。
動作の確認
Cluster環境でのいくつかの動作を確認してみます。
リダイレクト
-c
オプションをつけてredis-cliを起動すると、Cluster Modeでcliが起動して、コマンド実行時に適当なmaster nodeにリダイレクトしてくれるようなります。
$ redis-cli -c 127.0.0.1:6379> set key1 value1 -> Redirected to slot [9189] located at 127.0.0.1:6380 OK
A Redis client is free to send queries to every node in the cluster, including slave nodes. The node will analyze the query, and if it is acceptable (that is, only a single key is mentioned in the query, or the multiple keys mentioned are all to the same hash slot) it will lookup what node is responsible for the hash slot where the key or keys belong.
-c
オプションをつけない場合、リダイレクトされないため、接続しているnodeにkeyがない場合、処理に失敗します。
$ redis-cli 127.0.0.1:6379> get key1 (error) MOVED 9189 127.0.0.1:6380
keysは接続しているnodeのみを検索
nodeをまたいでkeyの検索はしてくれないようです。
$ redis-cli -c 127.0.0.1:6379> keys * (empty array) 127.0.0.1:6379> get key1 -> Redirected to slot [9189] located at 127.0.0.1:6380 "value1"
格納するmaster nodeを固定する
hash tag
というものを利用できるそうです。
There is an exception for the computation of the hash slot that is used in order to implement hash tags. Hash tags are a way to ensure that multiple keys are allocated in the same hash slot. This is used in order to implement multi-key operations in Redis Cluster.
In order to implement hash tags, the hash slot for a key is computed in a slightly different way in certain conditions. If the key contains a "{...}" pattern only the substring between { and } is hashed in order to obtain the hash slot.
こんな感じで、波括弧で囲んだ文字列にてhash値を取得してくれるため、同一のmasterにkeyが格納されることになります。
$ redis-cli -c 127.0.0.1:6379> set {key1}.one 1 -> Redirected to slot [9189] located at 127.0.0.1:6380 OK 127.0.0.1:6380> set {key1}.two 2 OK 127.0.0.1:6380> keys {key1}.* 1) "{key1}.one" 2) "{key1}.two"
msetコマンド利用時も、hash tagを利用することになります。
$ redis-cli -c 127.0.0.1:6379> mset {key2}.one 1 {key2}.two 2 OK 127.0.0.1:6379> mset key3.one 1 key3.two 2 (error) CROSSSLOT Keys in request don't hash to the same slot
cluster環境ではdatabaseが0のみとなる
Redis Cluster does not support multiple databases like the stand alone version of Redis. There is just database 0 and the SELECT command is not allowed.
とのこと。
$ redis-cli -c 127.0.0.1:6379> select 1 (error) ERR SELECT is not allowed in cluster mode
failoverの動作確認
failover時の動作を確認します。
プロセスの起動状況を確認。
$ ps -aef | grep redis | grep -v grep redis 827 1 0 22:46 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6381 [cluster] redis 829 1 0 22:46 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6380 [cluster] redis 832 1 0 22:46 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6382 [cluster] redis 834 1 0 22:46 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6384 [cluster] redis 836 1 0 22:46 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6383 [cluster] redis 2239 1 0 22:49 ? 00:00:00 /usr/local/bin/redis-server 127.0.0.1:6379 [cluster]
6379ポート起動のredisを停止します。
$ sudo systemctl stop redis-6379
該当のRedis Masterがfailとなり、slave(Replica)であったものがMasterに昇格しています。
$ redis-cli -p 6380 cluster nodes 35180c311d8b46fd9b824878d0384de97131b181 127.0.0.1:6379@16379 master,fail - 1591311034818 1591311032567 1 disconnected b3fa07636fc447b047f1ec18bb53d3b37697b807 127.0.0.1:6382@16382 master - 0 1591311074142 7 connected 0-5460 3a97895f36a696893292160e73c31c35ac3f9ddb 127.0.0.1:6381@16381 master - 0 1591311073632 3 connected 10923-16383 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb 127.0.0.1:6380@16380 myself,master - 0 1591311072000 2 connected 5461-10922 e73b19a1f3e60eb74992baeb8c6e183904bd8573 127.0.0.1:6384@16384 slave 3a97895f36a696893292160e73c31c35ac3f9ddb 0 1591311073000 6 connected 147be2a171022d5bdba3ca3a122cf1d3a29d7ab7 127.0.0.1:6383@16383 slave 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb 0 1591311073632 5 connected
停止したものを起動。
$ sudo systemctl start redis-6379
slave(Replica)として起動してきています。
$ redis-cli -p 6380 cluster nodes 35180c311d8b46fd9b824878d0384de97131b181 127.0.0.1:6379@16379 slave b3fa07636fc447b047f1ec18bb53d3b37697b807 0 1591311147097 7 connected b3fa07636fc447b047f1ec18bb53d3b37697b807 127.0.0.1:6382@16382 master - 0 1591311146079 7 connected 0-5460 3a97895f36a696893292160e73c31c35ac3f9ddb 127.0.0.1:6381@16381 master - 0 1591311147605 3 connected 10923-16383 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb 127.0.0.1:6380@16380 myself,master - 0 1591311147000 2 connected 5461-10922 e73b19a1f3e60eb74992baeb8c6e183904bd8573 127.0.0.1:6384@16384 slave 3a97895f36a696893292160e73c31c35ac3f9ddb 0 1591311148113 6 connected 147be2a171022d5bdba3ca3a122cf1d3a29d7ab7 127.0.0.1:6383@16383 slave 1e130c2c295bdb9cd7c03c86a5d7e2bc2c3925cb 0 1591311147000 5 connected