概要
前回の続きで今度はRedis Clusterを構築してスケール性などを検証してみます。
環境
- Redis 5.0.7
Redis Clusterの特徴
Redis Clusterは以下の特徴を持ちます。
- シャード毎にSlotを持ち、データ分散される(hash slot)
- 全部で16,384 slotsある
- ノードを追加して再シャードすることも可能(水平スケーリング)
- Replicationを持つことで冗長構成にもできる
- 通常ポートに+10000番したポートでCluster Busと呼ばれる接続がある
- 死活監視などに
システム図
冗長構成をとった時のシステム図は以下のようになります。
hash slot
Redis Clusterにはhash slotというデータ分散の仕組みがあります。
例えば3つのシャードがある場合、全16,384個あるslotsを
- [0-5460] (5461 slots)
- [5461-10922] (5462 slots)
- [10923-16383] (5461 slots)
といった形で分割します。
keyを登録する際にそのkeyがどのhash slotに入るかCRC16(mod 16384)で算出され、以下のようなイメージで分散されます。
Cluster Bus
Clusterを組んだ場合、通常ポートに+10000番したポートでCluster Busと呼ばれる接続が全ノード間で繋がっています。
Consulでも使っているGossip Protocolを使っており、信頼性のない通信路上でも多数のノードが耐障害性の高い情報共有を行うことができます。
Redis Clusterの構築
実際にRedis Clusterを構築してみます。
Masterのみ
まずは簡単のため、マスターだけで構築してみます。
システム図
イメージはこちら
設定
redis.conf
公式チュートリアルに合わせて以下のように用意します。
bind 0.0.0.0 port 6379 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
docker-compose.yaml
docker-composeで3台サクッと起動します。
version: '3' services: master_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 master_2: <<: *base master_3: <<: *base networks: redis_net: driver: bridge ipam: driver: default config: - subnet: 172.30.0.0/24
cluster構築
起動できたらその内1台に入ります。
$ docker exec -it cluster_master_1_1 /bin/ash
そしてcluster構築コマンドを実行します。
data# redis-cli --cluster create 172.30.0.2:6379 172.30.0.3:6379 172.30.0.4:6379
すると自動でシャードのslotsを配分してくれます。
>>> Performing hash slots allocation on 3 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 M: 04dce4d69ff508f7f66f7da20fd27280021ee156 172.30.0.2:6379 slots:[0-5460] (5461 slots) master M: 7164652a25ac5d286890fe134c7b45d663073a9b 172.30.0.3:6379 slots:[5461-10922] (5462 slots) master M: 734bd6fc695e958cdc6355135e64755495eaff0e 172.30.0.4:6379 slots:[10923-16383] (5461 slots) master 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: 04dce4d69ff508f7f66f7da20fd27280021ee156 172.30.0.2:6379 slots:[0-5460] (5461 slots) master M: 734bd6fc695e958cdc6355135e64755495eaff0e 172.30.0.4:6379 slots:[10923-16383] (5461 slots) master M: 7164652a25ac5d286890fe134c7b45d663073a9b 172.30.0.3:6379 slots:[5461-10922] (5462 slots) master [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
以上で作成できました。簡単ですね。
確認するとちゃんと3シャードでhash slotsが分散されています。
/data # redis-cli --cluster info 172.30.0.2:6379 172.30.0.2:6379 (04dce4d6...) -> 0 keys | 5461 slots | 0 slaves. 172.30.0.4:6379 (734bd6fc...) -> 0 keys | 5461 slots | 0 slaves. 172.30.0.3:6379 (7164652a...) -> 0 keys | 5462 slots | 0 slaves. [OK] 0 keys in 3 masters.
データ操作
普通にredis-cli
を実行すると、ハッシュキーが該当のノード出ない場合はエラーとなってしまいます。
/data # redis-cli 127.0.0.1:6379> set hoge fuga (error) MOVED 1525 172.30.0.2:6379
なので-c
オプションを付けて自動でリダイレクトしてもらうようにします。
/data # redis-cli -c
データを入れてみます。
127.0.0.1:6379> set piyo fuga -> Redirected to slot [10247] located at 172.30.0.3:6379 OK 172.30.0.3:6379> set hoge fuga -> Redirected to slot [1525] located at 172.30.0.2:6379 OK 172.30.0.2:6379> set dazo pizo OK
確認してみると分散されてはいっています。
/data # redis-cli --cluster info 172.30.0.2:6379 172.30.0.2:6379 (04dce4d6...) -> 2 keys | 5461 slots | 0 slaves. 172.30.0.4:6379 (734bd6fc...) -> 0 keys | 5461 slots | 0 slaves. 172.30.0.3:6379 (7164652a...) -> 1 keys | 5462 slots | 0 slaves. [OK] 3 keys in 3 masters.
取得も同様にリダイレクトされて取得できます。
127.0.0.1:6379> get piyo -> Redirected to slot [10247] located at 172.30.0.3:6379 "fuga" 172.30.0.3:6379> get hoge -> Redirected to slot [1525] located at 172.30.0.2:6379 "fuga" 172.30.0.2:6379> get dazo "pizo"
水平スケーリング
先程のクラスタで、台数を増やして水平スケーリングしてみます。
システム図
イメージはこちら
設定
コンテナ追加
docker-composeのscale outを実行します。
$ docker-compose scale master_1=2
シャード追加
次に既存のClusterに追加します。
第1引数は追加するノード、第2引数は任意の既存のノードです。
$ docker exec -it cluster_master_1_1 /bin/ash /data # redis-cli --cluster add-node 172.30.0.5:6379 172.30.0.2:6379 >>> Adding node 172.30.0.5:6379 to cluster 172.30.0.2:6379 >>> Performing Cluster Check (using node 172.30.0.2:6379) M: 04dce4d69ff508f7f66f7da20fd27280021ee156 172.30.0.2:6379 slots:[0-5460] (5461 slots) master M: 734bd6fc695e958cdc6355135e64755495eaff0e 172.30.0.4:6379 slots:[10923-16383] (5461 slots) master M: 7164652a25ac5d286890fe134c7b45d663073a9b 172.30.0.3:6379 slots:[5461-10922] (5462 slots) master [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. >>> Send CLUSTER MEET to node 172.30.0.5:6379 to make it join the cluster. [OK] New node added correctly.
ただしこのままだとhash slotsは新しいノードには配置されていません。
/data # redis-cli --cluster info 172.30.0.2:6379 172.30.0.2:6379 (04dce4d6...) -> 2 keys | 5461 slots | 0 slaves. 172.30.0.4:6379 (734bd6fc...) -> 0 keys | 5461 slots | 0 slaves. 172.30.0.3:6379 (7164652a...) -> 1 keys | 5462 slots | 0 slaves. 172.30.0.5:6379 (89f2c4d0...) -> 0 keys | 0 slots | 0 slaves. [OK] 3 keys in 4 masters.
再シャード
hash slotsを再配置するためにreshard
を実行します。
/data # redis-cli --cluster reshard 172.30.0.2:6379
するとslotsをどう分割するか聞かれます。
>>> Performing Cluster Check (using node 172.30.0.2:6379) M: 04dce4d69ff508f7f66f7da20fd27280021ee156 172.30.0.2:6379 slots:[0-5460] (5461 slots) master M: 734bd6fc695e958cdc6355135e64755495eaff0e 172.30.0.4:6379 slots:[10923-16383] (5461 slots) master M: 7164652a25ac5d286890fe134c7b45d663073a9b 172.30.0.3:6379 slots:[5461-10922] (5462 slots) master M: 89f2c4d05867bb7372ff414d9bccab47f6a3ce53 172.30.0.5:6379 slots: (0 slots) master [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. How many slots do you want to move (from 1 to 16384)?
16384を4ノードに分散するので16384 / 4 = 4096
にします。
How many slots do you want to move (from 1 to 16384)? 4096 What is the receiving node ID?
次にどのノードが新しくslotsを受け取るかを聞かれます。今回新しく追加したノードは89f2c4d05867bb7372ff414d9bccab47f6a3ce53
というIDなのでそれを入力します。
What is the receiving node ID? 89f2c4d05867bb7372ff414d9bccab47f6a3ce53 Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs.
次にどのノードからデータを動かすか聞かれるので、all
を選んで全ノードから動かすようにします。
Source node #1: all Ready to move 4096 slots. Source nodes: M: 04dce4d69ff508f7f66f7da20fd27280021ee156 172.30.0.2:6379 slots:[0-5460] (5461 slots) master M: 734bd6fc695e958cdc6355135e64755495eaff0e 172.30.0.4:6379 slots:[10923-16383] (5461 slots) master M: 7164652a25ac5d286890fe134c7b45d663073a9b 172.30.0.3:6379 slots:[5461-10922] (5462 slots) master Destination node: M: 89f2c4d05867bb7372ff414d9bccab47f6a3ce53 172.30.0.5:6379 slots: (0 slots) master Resharding plan: Moving slot 5461 from 7164652a25ac5d286890fe134c7b45d663073a9b Moving slot 5462 from 7164652a25ac5d286890fe134c7b45d663073a9b ︙ Moving slot 1363 from 04dce4d69ff508f7f66f7da20fd27280021ee156 Moving slot 1364 from 04dce4d69ff508f7f66f7da20fd27280021ee156 Do you want to proceed with the proposed reshard plan (yes/no)?
このようにプレビューが表示されるので、yes
を入力します。
するとゴリゴリと時間をかけて再配置が実施されます。
/data # redis-cli --cluster info 172.30.0.2:6379 172.30.0.2:6379 (04dce4d6...) -> 2 keys | 4096 slots | 0 slaves. 172.30.0.4:6379 (734bd6fc...) -> 0 keys | 4096 slots | 0 slaves. 172.30.0.3:6379 (7164652a...) -> 1 keys | 4096 slots | 0 slaves. 172.30.0.5:6379 (89f2c4d0...) -> 0 keys | 4096 slots | 0 slaves. [OK] 3 keys in 4 masters.
ちゃんと分散されました。
まとめ
Redis Clusterをdockerコンテナを用いて構築し、水平スケーリングを試してみました。
次回はRedis Clusterを冗長構成で構築してみます。