Carpe Diem

備忘録

Redis Clusterの構築と水平スケーリング

概要

christina04.hatenablog.com

前回の続きで今度はRedis Clusterを構築してスケール性などを検証してみます。

環境

  • Redis 5.0.7

Redis Clusterの特徴

Redis Clusterは以下の特徴を持ちます。

  • シャード毎にSlotを持ち、データ分散される(hash slot)
    • 全部で16,384 slotsある
    • ノードを追加して再シャードすることも可能(水平スケーリング)
  • Replicationを持つことで冗長構成にもできる
  • 通常ポートに+10000番したポートでCluster Busと呼ばれる接続がある
    • 死活監視などに

システム図

冗長構成をとった時のシステム図は以下のようになります。

f:id:quoll00:20200401024340p:plain

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)で算出され、以下のようなイメージで分散されます。

f:id:quoll00:20200401023501p:plain

Cluster Bus

Clusterを組んだ場合、通常ポートに+10000番したポートでCluster Busと呼ばれる接続が全ノード間で繋がっています。

f:id:quoll00:20200401104542p:plain

Consulでも使っているGossip Protocolを使っており、信頼性のない通信路上でも多数のノードが耐障害性の高い情報共有を行うことができます。

Redis Clusterの構築

実際にRedis Clusterを構築してみます。

Masterのみ

まずは簡単のため、マスターだけで構築してみます。

システム図

イメージはこちら

f:id:quoll00:20200401012657p:plain

設定

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"

水平スケーリング

先程のクラスタで、台数を増やして水平スケーリングしてみます。

システム図

イメージはこちら

f:id:quoll00:20200401012725p:plain

設定

コンテナ追加

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を冗長構成で構築してみます。

参考