Redis Clusterの構築

# Redis Cluster

2015/4/1 にRedis 3.0 がリリースされ、クラスタ機能がサポートされてます。

主に概要部分のSpecificationを翻訳していただいている方いますので、こちらが参考になります。
https://gist.github.com/key-amb/c641947a2139fdd81684


## 構成

最低3台でクラスターが構築可能だが、冗長性の確保のためにスレーブが必要。
最小構成は6台となる。

![redis_cluster.png](https://qiita-image-store.s3.amazonaws.com/0/49877/0f0f2cf6-2b89-ff54-e75f-6a42cf5458e6.png)



## 構築

検証等であれば、6つのプロセスを起動してRedis Clusterを構成する。
本番は6サーバで構成する。

### yum

```
sudo yum install gcc
```

### gem

```
gem install redis
``` 

### redis

```
wget http://download.redis.io/releases/redis-3.0.5.tar.gz
tar zxvf redis-3.0.5.tar.gz
cd redis-3.0.5
make 
sudo make install
```

### Redis起動

```
#!/bin/sh
/usr/local/bin/redis-server ./7000/redis.conf --pidfile ./7000/redis.pid --logfile ./7000/redis.log --cluster-config-file ./7000/node.conf&
/usr/local/bin/redis-server ./7001/redis.conf --pidfile ./7001/redis.pid --logfile ./7001/redis.log --cluster-config-file ./7001/node.conf&
/usr/local/bin/redis-server ./7002/redis.conf --pidfile ./7002/redis.pid --logfile ./7002/redis.log --cluster-config-file ./7002/node.conf&
/usr/local/bin/redis-server ./7003/redis.conf --pidfile ./7003/redis.pid --logfile ./7003/redis.log --cluster-config-file ./7003/node.conf&
/usr/local/bin/redis-server ./7004/redis.conf --pidfile ./7004/redis.pid --logfile ./7004/redis.log --cluster-config-file ./7004/node.conf&
/usr/local/bin/redis-server ./7005/redis.conf --pidfile ./7005/redis.pid --logfile ./7005/redis.log --cluster-config-file ./7005/node.conf&
```

redis.conf

```
port 7000 #7000-7005で6プロセス上げる
cluster-enabled yes # クラスター有効
cluster-node-timeout 5000 #milliseconds
appendonly no
loglevel verbose
```


## redis-trib.rb

クラスターの管理ツールである、redis-trib.rbを利用してクラスターの追加などを行う。
src配下にファイルがあります。

### クラスター構築

3Master/3Svale 
```
./redis-trib.rb create --replicas 1 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
```

rehashするので、yes/noを求められるがyesを入力。
コンバートが終われば、構築終了。

```
[OK] All 16384 slots covered
```


### ノード確認

ノードを確認

```
[ec2-user@ip-172-16-67-47 ~]$ redis-cli -p 7000 cluster nodes
8ae9c9637d95d5ff7924368b442a4d1e6db5980a 127.0.0.1:7002 slave 216f59dd653d218a47cfd1b5124438b6143dc808 0 1447646961055 7 connected
216f59dd653d218a47cfd1b5124438b6143dc808 127.0.0.1:7005 master - 0 1447646959553 7 connected 10923-16383
7215d76858af2d8f457b25f626989b2d8879bfac 127.0.0.1:7003 master - 0 1447646961557 8 connected 0-5460
25448e00f666a70c207803d1424e026a45d1bc49 127.0.0.1:7004 slave 56bde5b462a5676bb7aaf6cbae6b492aa0d1a4ca 0 1447646961557 5 connected
3d80f4a2d1d2f4beddf4a7cfbec902e75362bdf2 127.0.0.1:7000 myself,slave 7215d76858af2d8f457b25f626989b2d8879bfac 0 0 1 connected
56bde5b462a5676bb7aaf6cbae6b492aa0d1a4ca 127.0.0.1:7001 master - 0 1447646960554 2 connected 5461-10922
```


## 動作確認

redis-cliで動作を見てみると、
リダイレクトが行われset/getともに各クラスターに割り振られることがわかる。

```
[ec2-user@xxxxxxxxxx src]$ redis-cli -c -p 7000
127.0.0.1:7000> set num1 1
-> Redirected to slot [4980] located at 127.0.0.1:7003
OK
127.0.0.1:7003> set num2 2
-> Redirected to slot [8983] located at 127.0.0.1:7001
OK
127.0.0.1:7001> set num3 3
-> Redirected to slot [13110] located at 127.0.0.1:7005
OK
127.0.0.1:7001> get num1
-> Redirected to slot [4980] located at 127.0.0.1:7003
"1"
127.0.0.1:7003> get num2
-> Redirected to slot [8983] located at 127.0.0.1:7001
"2"
127.0.0.1:7001> get num3
-> Redirected to slot [13110] located at 127.0.0.1:7005
"3"
```


## reshard

指定のnodeからnodeへ指定のslotを移動させる場合

```
 ./redis-trib.rb reshard --from 56bde5b462a5676bb7aaf6cbae6b492aa0d1a4ca --to 7215d76858af2d8f457b25f626989b2d8879bfac --slots 100 127.0.0.1:7000
```

全ノードから特定のノードに指定のslotを移動させる場合

```
 ./redis-trib.rb reshard --from all --to 7215d76858af2d8f457b25f626989b2d8879bfac --slots 100 127.0.0.1:7000
```

## Failover

障害時はMasterからSlaveへ切り替わる。
検知時間+2〜3秒ほどかかる模様。
旧Masterが復旧したら自動的に、Slaveとなる。

slotを入れない、振り分けようのノードが合っても良いかと思うが、
性能面は不明。

## クライアント

複数のエンドポイントの記載が可能なクライアントを選定するようにする。
https://github.com/Grokzen/redis-py-cluster
https://github.com/nrk/predis
https://github.com/antirez/redis-rb-cluster