2014/01/21

忘れてたよ、ひとり ◯◯◯レポート - Redis Cluster

去年の夏に公開しようとしてたけど、すっかり忘れていた◯◯◯レポート

「はてブ」してくれると、とっても嬉しいです。よろしくお願いします。


ざーーっと、検証した結果なので、間違ってたり情報が古い可能性もあります。あしからず

タイトル : 

「Redis Cluster unstable でためしたよ(∩´∀`)∩ワーイ」


はじめに

去年の夏(2013)に作業した内容なので古いです。


環境
Amazon Linux AMI
  • ami-39b23d38 
Redis Cluster

  • github: https://github.com/antirez/redis
    • hash: cf71b82111e8e099b2667fc0126fe9624a1f69f7




現時点だと、unstableにclusterが入っているので、unstableをcloneして使用します。

今回は、Redis 2.9.11 (cf71b821/0) 64 bit を使用します。 ビルド/インストール mallocをどちらライブラリでするか選べます。

% make MALLOC=libc # defualt
or 
% make MALLOC=jemalloc 

verbose(詳細ログ)出すなら "V=1" をmakeのオプションに追加します。


make install でインストール先を変更する場合は、

$ make PREFIX=/some/other/directory install


 を実行します。


build

% make MALLOC=jemalloc V=1
※ make install しなくても、srcフォルダ内でredisを起動することができるので今回は実行しません。

Amazon Linuxでのインストール例

# sudo su - 
# yum -y install gcc
# git clone https://github.com/antirez/redis.git
# git checkout -b cf71b82111e8e099b2667fc0126fe9624a1f69f7 cf71b82111e8e099b2667fc0126fe9624a1f69f7
# cd redis
# cd deps/; make jemalloc; cd ../; make clean; make MALLOC=jemalloc 

クライアントの場合は追加で下記も

# yum -y install rubygems
# gem install redis

Cluster機能で追加になった設定項目 クラスタの設定は現時点で3つあります。


クラスタとして動作可否
cluster-enabled yes 

クラスタ情報管理ファイル名
cluster-config-file nodes-6379.conf 

※各クラスタノードはクラスタ情報を設定ファイルで自動管理します。


ノードのタイムアウト
cluster-node-timeout 5 


追記専用モードON ディスク書き出し
append only yes

※クラスタ機能で追加されたものではないが、推奨設定なので記載


設定ファイル全体

※ポート重複しなければ、同一サーバーにN台起動可能

daemonize no
pidfile /var/run/redis.pid
port 6379
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1
timeout 0
tcp-keepalive 0
loglevel notice
#logfile "/tmp/redis.6379.log"
# syslog-enabled no
# syslog-ident redis
# syslog-facility local0
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
# slaveof  
# masterauth 
slave-serve-stale-data yes
slave-read-only yes
# repl-ping-slave-period 10
# repl-timeout 60
repl-disable-tcp-nodelay no
# repl-backlog-size 1mb
# repl-backlog-ttl 3600
slave-priority 100
# min-slaves-to-write 3
# min-slaves-max-lag 10
# requirepass foobared
# rename-command CONFIG ""
# maxclients 10000
# maxmemory 
# maxmemory-policy volatile-lru
# maxmemory-samples 3
#appendonly no
appendonly yes
# appendfsync always
appendfsync everysec
# appendfsync no
no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000

# -- cluster
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 5

slowlog-log-slower-than 10000
slowlog-max-len 128
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
# include /path/to/other.conf



起動

redis-serverの起動オプション
$ .src/redis-server --help

Usage: ./redis-server [/path/to/redis.conf] [options]
       ./redis-server - (read config from stdin)
       ./redis-server -v or --version
       ./redis-server -h or --help
       ./redis-server --test-memory 

Examples:
       ./redis-server (run the server with default conf)
       ./redis-server /etc/redis/6379.conf
       ./redis-server --port 7777
       ./redis-server --port 7777 --slaveof 127.0.0.1 8888
       ./redis-server /etc/myredis.conf --loglevel verbose

Sentinel mode:
       ./redis-server /etc/sentinel.conf --sentinel


上記で作成した設定ファイルを使って起動します。 ※Daemon offなので、3枚ターミナルを開いて別々に起動してください。

起動コマンド


$ ./src/redis-server ./conf/redis.0.conf 

起動確認

下記のような情報が出力されればOKです。
※「Running in cluster mode」と表示されていれば、clusterが利用可能です。

[41053] 24 Jul 11:57:31.469 * Max number of open files set to 10032
[41053] 24 Jul 11:57:31.470 * Node configuration loaded, I'm 24dfdc877af46566ebb7228440257d057964463d
                _._                                                 
           _.-``__ ''-._                                            
      _.-``    `.  `_.  ''-._           Redis 2.9.11 (cf71b821/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                  
 (    '      ,       .-`  | `,    )     Running in cluster mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 41053
  `-._    `-._  `-./  _.-'    _.-'                                  
 |`-._`-._    `-.__.-'    _.-'_.-'|                                 
 |    `-._`-._        _.-'_.-'    |           http://redis.io       
  `-._    `-._`-.__.-'_.-'    _.-'                                  
 |`-._`-._    `-.__.-'    _.-'_.-'|                                 
 |    `-._`-._        _.-'_.-'    |                                 
  `-._    `-._`-.__.-'_.-'    _.-'                                  
      `-._    `-.__.-'    _.-'                                      
          `-._        _.-'                                          
              `-.__.-'                                              

[41053] 24 Jul 11:57:31.470 # Server started, Redis version 2.9.11
[41053] 24 Jul 11:57:31.471 * The server is now ready to accept connections on port 6379


vm.overcommit_memory警告

[27432] 26 Jul 09:48:45.627 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.


上記のエラーの対応方法
# 設定
$ vi /etc/sysctl.conf
vm.overcommit_memory = 1 # 追加

クライアント接続
cluster設定していない状態で、コマンドラインクライアントから接続し、簡単な操作を行います。

従来のRedis接続

$ ./src/redis-cli -p 6379
127.0.0.1:6379>

クラスタでのRedis接続

$ ./src/redis-cli -p 6379 -c
※ clusterに接続する際は、"-c"をつける必要がある。

redis-cli コマンドオプション
$ ./src/redis-cli --help
redis-cli 2.9.11 (git:cf71b821)

Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]
  -h      Server hostname (default: 127.0.0.1)
  -p          Server port (default: 6379)
  -s        Server socket (overrides hostname and port)
  -a      Password to use when connecting to the server
  -r        Execute specified command N times
  -i      When -r is used, waits  seconds per command.
                    It is possible to specify sub-second times like -i 0.1
  -n            Database number
  -x                Read last argument from STDIN
  -d     Multi-bulk delimiter in for raw formatting (default: \n)
  -c                Enable cluster mode (follow -ASK and -MOVED redirections)
  --raw             Use raw formatting for replies (default when STDOUT is
                    not a tty)
  --latency         Enter a special mode continuously sampling latency
  --latency-history Like --latency but tracking latency changes over time.
                    Default time interval is 15 sec. Change it using -i.
  --slave           Simulate a slave showing commands received from the master
  --rdb   Transfer an RDB dump from remote server to local file.
  --pipe            Transfer raw Redis protocol from stdin to server
  --bigkeys         Sample Redis keys looking for big keys
  --eval      Send an EVAL command using the Lua script at 
  --help            Output this help and exit
  --version         Output version and exit

Examples:
  cat /etc/passwd | redis-cli -x set mypasswd
  redis-cli get mypasswd
  redis-cli -r 100 lpush mylist x
  redis-cli -r 100 -i 1 info | grep used_memory_human:
  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3
  (Note: when using --eval the comma separates KEYS[] from ARGV[] items)

When no command is given, redis-cli starts in interactive mode.
Type "help" in interactive mode for information on available commands.


クラスタノードの状態


$ ./src/redis-cli -p 6379
127.0.0.1:6379>

現在のクラスタノード情報表示


> cluster nodes
24dfdc877af46566ebb7228440257d057964463d :0 myself,master - 0 0 connected

クラスタの設定をしていないので、接続したクラスタノード情報しか表示されていません。

$ ./src/redis-cli -p 6380
127.0.0.1:6380> cluster nodes
e8ff1558c29e3f3937750a36b2b1848659ceb39d :0 myself,master - 0 0 connected

2台目のRedisも自身のクラスタノード情報しか表示されません。

クラスタノード情報は、設定ファイルで指定した cluster-config-file nodes-{XXX}.conf に自動で書き込まれています。

ノード情報ファイル

$ cat nodes-6379.conf
24dfdc877af46566ebb7228440257d057964463d :0 myself,master - 0 0 connected


クラスタの設定

クラスタの操作には、Redisがredis-trib.rbを用意してくれています。

redis-trib.rbのコマンドオプション

$ ./src/redis-trib.rb
Usage: redis-trib  

  reshard    host:port
  addnode    new_host:new_port existing_host:existing_port
  check      host:port
  create     host1:port1 ... hostN:portN
  fix        host:port
  help       (show this help)



redis-trib.rb実行エラー

redid-trib.rb実行時に、`gem_original_require': no such file to load -- redis (LoadError) の ようなエラーが出た場合は、rubyのredisライブリをインストールする必要があります。

依存ライブラリインストール
$ sudo gem install redis 


クラスタの作成
$ ./src/redis-trib.rb create 127.0.0.1:6379 127.0.0.1:6380
>>> Creating cluster
Connecting to node 127.0.0.1:6379: OK
Connecting to node 127.0.0.1:6380: OK
>>> Performing hash slots allocation on 2 nodes...
M: 41c30fcfc47daab3a409ad908da45d79bdcd9b6a 127.0.0.1:6379
   slots:0-8191 (8192 slots) master
M: 5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380
   slots:8192-16383 (8192 slots) master
Can I set the above configuration? (type 'yes' to accept): yes # この時点でslotまでは作成されている
>>> Nodes configuration updated
>>> 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: 41c30fcfc47daab3a409ad908da45d79bdcd9b6a 127.0.0.1:6379
   slots:0-8191 (8192 slots) master
M: 5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380
   slots:8192-16383 (8192 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage…


クラスタ作成時のログ

127.0.0.1:6379のログ
[3234] 25 Jul 11:30:08.147 # Cluster state changed: ok

127.0.0.1:6380のログ
[3244] 25 Jul 11:30:08.074 - Accepted cluster node 127.0.0.1:51492
[3244] 25 Jul 11:30:08.074 # Cluster state changed: ok 


クラスタの情報表示

$ ./src/redis-cli -p 6379 -c 

redis 127.0.0.1:6379> cluster nodes
5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380 master - 0 1374719962 connected 8192-16383
41c30fcfc47daab3a409ad908da45d79bdcd9b6a :0 myself,master - 0 0 connected 0-8191





Clusterでの各種クエリーの動作状況一覧



Command : SET

$ ./src/redis-cli -c -p 6380
redis 127.0.0.1:6380> SET set0 val0
-> Redirected to slot [7164] located at 127.0.0.1:6379
OK
redis 127.0.0.1:6379> SET set1 val1
OK

6380に接続したが、set0は、6379が担当なのでRedirectedされた。 ※ "Redirected to slot [7164] located at 127.0.0.1:6379" が発生すると terminalも6379に移動しているので注意が必要。

Command : GET

redis 127.0.0.1:6379> GET set0
-> Redirected to slot [9189] located at 127.0.0.1:6380
"val0"

※ GETもSETと同様に、"Redirected to slot [9189] located at 127.0.0.1:6380" が発生すると、terminalも6380に移動しているので注意が必要。

Command : MGET


redis 127.0.0.1:6380> MGET set0 set1
(error) ERR Multi keys request invalid in cluster

※Redis clusterでは現時点で、multi keysを使った処理ができない。

Command : INCR


$ ./src/redis-cli -c -p 6379
redis 127.0.0.1:6379> SET incr 0
-> Redirected to slot [10851] located at 127.0.0.1:6380
OK
redis 127.0.0.1:6380> INCR incr
(integer) 1
redis 127.0.0.1:6380> GET incr
"1"
redis 127.0.0.1:6380> INCR incr
(integer) 2
redis 127.0.0.1:6380> GET incr
"2"


Command : LPUSH/LRANGE/LPOP

$ ./src/redis-cli -c -p 6379
redis 127.0.0.1:6379> LPUSH list0 "list0-0"
(integer) 1
redis 127.0.0.1:6379> LPUSH list0 "list0-1"
(integer) 2
redis 127.0.0.1:6379> LPUSH list0 "list0-2"
(integer) 3
redis 127.0.0.1:6379> LPUSH list0 "list0-3"
(integer) 4
redis 127.0.0.1:6379> LRANGE list0 0 -1
1) "list0-3"
2) "list0-2"
3) "list0-1"
4) "list0-0"
redis 127.0.0.1:6379> LPOP list0
"list0-3"
redis 127.0.0.1:6379> LPOP list0
"list0-2"
redis 127.0.0.1:6379> LRANGE list0 0 -1
1) "list0-1"
2) "list0-0"


Command : PING

$ ./src/redis-cli -c -p 6379
redis 127.0.0.1:6379> PING
PONG



Command: SADD/SMEMBERS

$ ./src/redis-cli -c -p 6379
redis 127.0.0.1:6379> SADD myset "Hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset "World"
(integer) 1
redis 127.0.0.1:6379> SADD myset "World"
(integer) 0
redis 127.0.0.1:6379> SMEMBERS myset
1) "World"
2) "Hello"


Command : ZADD/ZRANGE(WITHSCORES)

$ ./src/redis-cli -c -p 6379
redis 127.0.0.1:6379> ZADD myzset 1 "one"
(integer) 1
redis 127.0.0.1:6379> ZADD myzset 1 "uno"
(integer) 1
redis 127.0.0.1:6379> ZADD myzset 1 "two"
(integer) 1
redis 127.0.0.1:6379> ZADD myzset 1 "two"
(integer) 0
redis 127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "1"
5) "uno"
6) "1"
redis 127.0.0.1:6379> ZRANGE myzset 0 -1
1) "one"
2) "two"
3) "uno"


Command: HSET/HGET/HMGET/HVALS

$ ./src/redis-cli -c -p 6379
redis 127.0.0.1:6379> HSET myhash field1 "Hello"
-> Redirected to slot [9295] located at 127.0.0.1:6380
(integer) 0
redis 127.0.0.1:6380> HSET myhash field2 "World"
(integer) 1
redis 127.0.0.1:6380> HMGET myhash field1 field2 nofield
1) "Hello"
2) "World"
3) (nil)
redis 127.0.0.1:6380> HVALS myhash
1) "Hello"
2) "World"


Command : MSET/HMSET

$ ./src/redis-cli -c -p 6379
redis 127.0.0.1:6379> MSET key1 "Hello" key2 "World"
(error) ERR Multi keys request invalid in cluster
redis 127.0.0.1:6379> HMSET myhash field1 "Hello" field2 "World"
-> Redirected to slot [9295] located at 127.0.0.1:6380
OK
redis 127.0.0.1:6380> HGET myhash field1
"Hello"
redis 127.0.0.1:6380> HGET myhash field2
"World"

※ Redis clusterでは現時点で、multi keysを使った処理ができない。 ※ HMSETもエラーになると思うが、Hashはこの場合 "myhash"がKeyなので、multi-keyではないため利用することが可能です。ただしhash内のデータ分散は当然出来ない。



Command : FLUSHALL

データ全部削除
$ ./src/redis-cli -c
redis 127.0.0.1:6379> flushall
OK
redis 127.0.0.1:6379> keys *
(empty list or set)


※クラスタ内のデータ全消去ではなく、redis-cliでアクセスしたサーバーのデータのみです。 クラスタ内のデータすべてを消したい場合は、すべてのサーバーにアクセスして個別に削除する必要があります。



Command : INFO

Redisのサーバー情報を表示出来ます。
※ CONFIGデータも見れるので、設定ファイルとメモリのCONFIGの付け合せ等で利用したりします


$ ./src/redis-cli -c
redis 127.0.0.1:6379> INFO
# Server
redis_version:2.9.11
redis_git_sha1:cf71b821
redis_git_dirty:0
redis_build_id:5de4b123ad1e29d1
redis_mode:cluster
os:Darwin 12.4.0 x86_64





Queryモニタリング

※ 前提条件 : バックエンドで、SET/GETを定期的に実行している状態(fkei:{連番}をセットしている)
$ ./src/redis-cli monitor 
OK
1374806395.553176 [0 127.0.0.1:50640] "info"
1374806395.559106 [0 127.0.0.1:50640] "cluster" "nodes"
1374806395.822805 [0 127.0.0.1:50641] "info"
1374806395.824347 [0 127.0.0.1:50641] "set" "fkei:1" "2013615113955820"
1374806396.333129 [0 127.0.0.1:50641] "get" "fkei:1"
1374806397.363962 [0 127.0.0.1:50641] "set" "fkei:4" "2013615113957363"
1374806397.871904 [0 127.0.0.1:50641] "get" "fkei:4"


Clusterのモニタリングはサポーされておらず、接続した、Redisサーバー単体のモニタリングになります。

 fkei:2は別のRedisにSETされたため、Monitorには、情報が表示されていない。



情報チェックコマンド (redis-trib.rb check)

$ ./src/redis-trib.rb check 127.0.0.1:6379
Connecting to node 127.0.0.1:6379: OK
Connecting to node 127.0.0.1:6380: OK
>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: 41c30fcfc47daab3a409ad908da45d79bdcd9b6a 127.0.0.1:6379
   slots:0-8191 (8192 slots) master
M: 5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380
   slots:8192-16383 (8192 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.






redis-trib.rbコマンドで失敗した場合の復旧コマンド(redis-trib.rb fix)


 例)redis-trib.rb create でslots作成は成功したが、nodeのアップデートで失敗した場合に使用すると、リカバリーすることができます。

$ ./src/redis-trib.rb fix 127.0.0.1:6379
Connecting to node 127.0.0.1:6379: OK
Connecting to node 127.0.0.1:6380: OK
>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: 41c30fcfc47daab3a409ad908da45d79bdcd9b6a 127.0.0.1:6379
   slots:0-8191 (8192 slots) master
M: 5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380
   slots:8192-16383 (8192 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.





Redis clusterにnodeを追加

localhostに6379, 6380のクラスタがある状態で6381を追加します。

node現状確認

$ ./src/redis-cli -c -p 6379
redis 127.0.0.1:6379> cluster nodes
5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380 master - 0 1374807490 connected 8192-16383
41c30fcfc47daab3a409ad908da45d79bdcd9b6a :0 myself,master - 0 0 connected 0-8191


$ ./src/redis-cli -c -p 6380
redis 127.0.0.1:6380> cluster nodes
5c7710631d4768055322561911160484768ae1c2 :0 myself,master - 0 0 connected 8192-16383
41c30fcfc47daab3a409ad908da45d79bdcd9b6a 127.0.0.1:6379 master - 0 1374807499 connected 0-8191


$ ./src/redis-cli -c -p 6381
redis 127.0.0.1:6381> cluster nodes
89efa9843b95ebb32184ad1f766e2905723851a3 :0 myself,master - 0 0 connected





ノード追加コマンド(redis-trib.rb addnode) 


6381を6379のクラスタに追加する。
$ ./src/redis-trib.rb addnode 127.0.0.1:6381 127.0.0.1:6379
>>> Adding node 127.0.0.1:6381 to cluster 127.0.0.1:6379
Connecting to node 127.0.0.1:6379: OK
Connecting to node 127.0.0.1:6380: OK
>>> Performing Cluster Check (using node 127.0.0.1:6379)
M: 41c30fcfc47daab3a409ad908da45d79bdcd9b6a 127.0.0.1:6379
   slots:0-8191 (8192 slots) master
M: 5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380
   slots:8192-16383 (8192 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
Connecting to node 127.0.0.1:6381: OK
>>> Send CLUSTER MEET to node 127.0.0.1:6381 to make it join the cluster.


現状確認

$ ./src/redis-cli -c -p 6379
redis 127.0.0.1:6379> cluster nodes
5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380 master - 0 1374807563 connected 8192-16383
89efa9843b95ebb32184ad1f766e2905723851a3 127.0.0.1:6381 master - 0 1374807564 connected
41c30fcfc47daab3a409ad908da45d79bdcd9b6a :0 myself,master - 0 1374807564 connected 0-8191


$ ./src/redis-cli -c -p 6380
redis 127.0.0.1:6380> cluster nodes
89efa9843b95ebb32184ad1f766e2905723851a3 127.0.0.1:6381 master - 0 1374807567 connected
5c7710631d4768055322561911160484768ae1c2 :0 myself,master - 0 1374807567 connected 8192-16383
41c30fcfc47daab3a409ad908da45d79bdcd9b6a 127.0.0.1:6379 master - 0 1374807568 connected 0-8191
redis 127.0.0.1:6380>

$ ./src/redis-cli -c -p 6381
redis 127.0.0.1:6381> cluster nodes
89efa9843b95ebb32184ad1f766e2905723851a3 :0 myself,master - 0 1374807570 connected
5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380 master - 0 1374807571 connected 8192-16383
41c30fcfc47daab3a409ad908da45d79bdcd9b6a 127.0.0.1:6379 master - 0 1374807572 connected 0-8191



データ再配置(redis-trib.rb reshard)

ノード追加だけでは、データの再配置は起こりません。
appendで追加したRedisサーバーにスロットを割り当て、データの再配置を行う。

$ ./src/redis-trib.rb reshard 127.0.0.1:6379
Connecting to node 127.0.0.1:6381: OK
Connecting to node 127.0.0.1:6380: OK
Connecting to node 127.0.0.1:6379: OK
>>> Performing Cluster Check (using node 127.0.0.1:6381)
M: 89efa9843b95ebb32184ad1f766e2905723851a3 127.0.0.1:6381
   slots: (0 slots) master
M: 5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380
   slots:13653-16383 (2731 slots) master
M: 41c30fcfc47daab3a409ad908da45d79bdcd9b6a 127.0.0.1:6379
   slots:0-13652 (13653 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)? 1024
What is the receiving node ID? 89efa9843b95ebb32184ad1f766e2905723851a3
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.
Source node #1:all
……
……
……
……


上記コマンドを使用し、何度かslotsを最適化すると、下記のようなslots配置になります。

$ ./src/redis-cli -c
redis 127.0.0.1:6379> cluster nodes
5c7710631d4768055322561911160484768ae1c2 127.0.0.1:6380 master - 0 1374816113 connected 0-1109 3666-6651 15103-16383
89efa9843b95ebb32184ad1f766e2905723851a3 127.0.0.1:6381 master - 0 1374816112 connected 1110-3665 14677-15102
41c30fcfc47daab3a409ad908da45d79bdcd9b6a :0 myself,master - 0 1374816111 connected 6652-14676





エラーケース

reshard中にset等が実行されると、エラーにはならないで動作するとブログ等で書かれていますが、今回試しに、setを大量に行いながらreshardすると、下記のようなエラーが発生しました。

[Error: Error: MOVED 8541 127.0.0.1:6381]

そして、すでにあるデータをgetしても、あるはずのデータが(nil)で返却されました。どうやらデータが何処かに入ってしまったみたいです。

Release前には修正されると思いますが、メモがてら



異常系 #1

Redis clusterの1台をkill した場合の挙動

redis 127.0.0.1:6379> get fkei:2:1
(error) CLUSTERDOWN The cluster is down. Use CLUSTER INFO for more information
redis 127.0.0.1:6379> cluster info
cluster_state:fail
cluster_slots_assigned:16384
cluster_slots_ok:12384
cluster_slots_pfail:0
cluster_slots_fail:4000
cluster_known_nodes:3
cluster_size:3

killしていないRedisサーバーのログ

[16082] 29 Jul 13:36:10.765 # Cluster state changed: fail 



killしたサーバーを再起動した時のkillしていないサーバーのログ

[16087] 29 Jul 13:37:03.190 * Clear FAIL state for node 37445b3c34f8b0f5da5285ec6c65cf36ae67f57f: is reachable again and nobody is serving its slots after some time.
[16087] 29 Jul 13:37:03.190 # Cluster state changed: ok
[16087] 29 Jul 13:37:03.190 - Accepted cluster node 127.0.0.1:56480
[16087] 29 Jul 13:37:04.212 * Node 95de2a8f1aca180337dfdcc5ffab032d23acb089 reported node 37445b3c34f8b0f5da5285ec6c65cf36ae67f57f is back online.






レプリケーション作成

レプリケーション(Master-Slave)を設定する。

Slaveで設定コマンド実行

src/redis-cli -p 6381 -c redis
127.0.0.1:6381> cluster nodes
466373eb84d43ab37b26809004dacc956f3ca8f4 127.0.0.1:6379 master - 0 1375073164 connected 0-8191
f7b564f3e66869f49010e3368ec039cf01bf3667 127.0.0.1:6380 master - 0 1375073163 connected 8192-16383
4afea58d10fd824453bedf9bfc73bdacc5a815b0 :0 myself,master - 0 1375073158 connected

redis 127.0.0.1:6381> cluster replicate 466373eb84d43ab37b26809004dacc956f3ca8f4
OK


Master 側
[16135] 29 Jul 13:47:07.843 - Accepted 127.0.0.1:56789
[16135] 29 Jul 13:47:07.844 * Slave asks for synchronization
[16135] 29 Jul 13:47:07.844 * Full resync requested by slave.
[16135] 29 Jul 13:47:07.844 * Starting BGSAVE for SYNC
[16135] 29 Jul 13:47:07.845 * Background saving started by pid 16168
[16168] 29 Jul 13:47:07.846 * DB saved on disk
[16135] 29 Jul 13:47:07.941 * Background saving terminated with success
[16135] 29 Jul 13:47:07.941 * Synchronization with slave succeeded



Slave側
[16154] 29 Jul 13:47:07.843 * Connecting to MASTER...
[16154] 29 Jul 13:47:07.843 * MASTER <-> SLAVE sync started
[16154] 29 Jul 13:47:07.844 * Non blocking connect for SYNC fired the event.
[16154] 29 Jul 13:47:07.844 * Master replied to PING, replication can continue...
[16154] 29 Jul 13:47:07.844 * Partial resynchronization not possible (no cached master)
[16154] 29 Jul 13:47:07.844 * Full resync from master: c94091f0d2e9bee1c90efc63c6382188bf38660f:1
[16154] 29 Jul 13:47:07.941 * MASTER <-> SLAVE sync: receiving 18 bytes from master
[16154] 29 Jul 13:47:07.941 * MASTER <-> SLAVE sync: Loading DB in memory
[16154] 29 Jul 13:47:07.941 * MASTER <-> SLAVE sync: Finished with success
[16154] 29 Jul 13:47:07.942 * Background append only file rewriting started by pid 16169
[16169] 29 Jul 13:47:07.942 * SYNC append only file rewrite performed
[16154] 29 Jul 13:47:07.943 * Background AOF rewrite terminated with success
[16154] 29 Jul 13:47:07.943 * Parent diff successfully flushed to the rewritten AOF (0 bytes)
[16154] 29 Jul 13:47:07.943 * Background AOF rewrite finished successfully
[16154] 29 Jul 13:47:07.943 - Background AOF rewrite signal handler took 121us


レプリケーション台数が通常のクラスタより多い問題
Cassandraのような1ノードが複数のノードデータを持つタイプではなく、MongoDBのレプリケーションに近い。

下記のような相互レプリはできないようです。

6379(Master) -> 6380(Slave) and 6380(Master) -> 6379(Slave)



Backup/Restore

※※※※※完全に検証されていない
単体のdumpなら取れるが、クラスタ全体のdumpを取る仕組みはないかも。。。。


まとめ


利便性について

multi-keyが使えないという制約がstableになっても付くようです。
一つのキー だけでほとんどのケースが問題ないものは、特に利便性が下がる気はしません。また。listやhashは使えるので、これまでどおりのデータアクセスはできる気がする。




安定性について

今年中にstableをリリースしたいと、本家が言っているがかなりクラスタ部分の不具合が多く、少しでもイレギュラケースや高負荷時の障害検証をするとすぐにクラスタ内のデータがみれなくなり、clusterコマンド(-c)でデータが見れなくなる(単体のredisにアクセスすると見れるケースもある)。


※異常ケースを起こさないで通常の負荷をかけると、特に不具合はなかった。
※自作プログラムで負荷かけただけなので指標としてはおすすめしません。ちゃんとしたのでためした方がいいよ(∩´∀`)∩ワーイ



clusterの管理について

CassandraやRiakといった代表的なNoSQLとは違い、良くも悪くも手動でスロットの割り振りが可能なので、障害によって最新のデータが見つけられないと言った致命的な状態にはならないと思われる。
モニタリングやチェッカー、ステータスはまだ、unstableということもありCluster未対応がおおい。ココらへんも出揃ってきたところで導入を検討したほうが良い気がする。




感想


Redis-Clusterは、Cassandra(クラスタ)とMongoDB(mongoc)の中間みたいなCluster管理を行っているので、比較的容易に運用できる気がしている。


だが、まだまだ本番運用するほど安定していないので、しばらく様子見というところです。
今の品質だと、今年中にstableは出ない気がします。






OSS管理ツール

商用クラウド

redis-cloud



特徴

インフラ、管理ツールなどをセットで提供
node間のmulti List/Set/Sorted-Setをサポート





参考URL



動画



PDF



クライアントライブラリ

node.js

※cluster nodeの正規表現がバグっている、sourceからインストールして少し修正する必要がある。

python

※未検証


ruby

※Redis本家が使っているので、カバレッジ100%な気がする。