RedisClusterをちょっとだけ試してみる。
この記事はMikeTOKYO Advent Calendar 2013の6日目です。
こんばんわ、osawagiboyです。
まさかのこの日に初投稿です。
さて、まさかのクリスマス・イブの日とリリース前のこの状況でやろうぜと
誘っていただいたチャンタケ氏恨みます。感謝します。
タイトルどおり、今流行りのRedisのクラスタ構成を組めるRedis-Clusterを使えるか試してみました。
ちなみにまだunstableです。
というのもsocket.ioでRedisを共有ストアとして利用した場合、チャンタケ氏が公開しているこちらにも書いている通り
構成やRedisサーバのスケールが少し複雑かつ面倒というのを解決できへんかなーと。
Redis clusterの詳細については こちらを参照してください。
Cassandraなどと同様、クラスタ間をGossipでやりとりするようですね。
とりあえず試します。
むっちゃ長くなってしまった・・・。
環境構築
Vagrantを使ってVirtualBox上にクラスタを構成します。
RedisClusterインストール
利用するポートはmasterでポート:(6301,6302,6303)を構築します。
[vagrant@localhost src]$ sudo git clone https://github.com/antirez/redis [vagrant@localhost redis]$ sudo make MALLOC=jemalloc [vagrant@localhost redis]$ sudo make install
mallocのライブラリをjemallocにした以外は基本デフォルトでさくっと入れちゃいます。
詳細は公式のgithubをみてください。
redis.conf設定
設定ファイルは基本デフォルトで各ポート用に変更しています。
現状Clusterの設定は3つあります。
cluster-enabled yes
=> クラスタモード
cluster-config-file nodes-6301.conf
=> 自クラスタ情報の管理ファイル名
cluster-node-timeout 5
=> 各ノードのタイムアウト
今回使う設定。※Master用
daemonize no pidfile /var/run/redis.pid port 6301 timeout 0 tcp-keepalive 0 loglevel notice logfile "./redis-6301.log" 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 ./ slave-serve-stale-data yes slave-read-only yes repl-disable-tcp-nodelay no slave-priority 100 appendonly no appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb lua-time-limit 5000 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 # ----cluster---- # # cluster-enabled <span style="color: #ff2600">yes</span> cluster-config-file /etc/redis/nodes-6301.conf
ClusterModeでRedis起動
ではMasterの6301,6302,6303を起動!
vm.overcommit_memory = 1設定しておかないとwarning出ます。
[vagrant@localhost redis]$ sudo /usr/local/bin/redis-server /etc/redis/redis-6301.conf [12180] 24 Dec 03:04:17.249 * Max number of open files set to 10032 [12180] 24 Dec 03:04:17.250 * Node configuration loaded, I'm bf7b266d12345fd68d7f7c9233bcd71d473f0a41 _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 2.9.11 (e7893842/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in cluster mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6301 | `-._ `._ / _.-' | PID: 12180 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' [12180] 24 Dec 03:04:17.250 # Server started, Redis version 2.9.11 [12180] 24 Dec 03:04:17.251 * The server is now ready to accept connections on port 6301
起動するとnodes-6301.confファイルのようにCluster情報を管理します。
まだクラスタを組んでいないので、自分しかいませんが。
[vagrant@localhost redis]$ sudo cat nodes-6301.conf ec77ab685cc6ae9a8ebbf59de0da12d8537801c4 :0 myself,master - 0 0 0 connected [vagrant@localhost redis]$ sudo cat nodes-6302.conf b1eeb99149cc25514791474e445098d435b4215c :0 myself,master - 0 0 0 connected [vagrant@localhost redis]$ sudo cat nodes-6303.conf 65663be105a627ed06163c4e1ef95bbf997ce937 :0 myself,master - 0 0 0 connected
また、redis-cliでも確認できます。
[vagrant@localhost redis]$ sudo /usr/local/bin/redis-cli -p 6301 cluster nodes ec77ab685cc6ae9a8ebbf59de0da12d8537801c4 :0 myself,master - 0 0 0 connected [vagrant@localhost redis]$ sudo /usr/local/bin/redis-cli -p 6302 cluster nodes b1eeb99149cc25514791474e445098d435b4215c :0 myself,master - 0 0 0 connected [vagrant@localhost redis]$ sudo /usr/local/bin/redis-cli -p 6303 cluster nodes 65663be105a627ed06163c4e1ef95bbf997ce937 :0 myself,master - 0 0 0 connected
ちなみにnodes-{port}.confファイルを削除してRedisを再起動すると新規クラスタとして起動しました。
Cassandraとかは一度起動すればRing情報をデータに持っていたけど、RedisClusterもディスク書き出ししていれば、保存されるのかな?
今度試してみます。
クラスタを構成
では本命のクラスタを構成します!
RedisClusterの管理ツールとしてredis-trib.rbが用意されていますので、こちらで追加していきたいと思います。
[vagrant@localhost redis]$ sudo src/redis-trib.rb src/redis-trib.rb:24:in `require': no such file to load -- rubygems (LoadError) from src/redis-trib.rb:24
あれ!?と思ったらredisのrubyライブラリが必要なようです。
ライブラリいれて気を取り直し・・・めんどいのでrootでいきます。
[root@localhost redis]# src/redis-trib.rb Usage: redis-trib <command> <options> <arguments ...> create host1:port1 ... hostN:portN check host:port fix host:port reshard host:port addnode new_host:new_port existing_host:existing_port help (show this help)
無事使えるようなのでクラスタを構成していきます。
[root@localhost redis]# ./src/redis-trib.rb create 127.0.0.1:6301 127.0.0.1:6302 >>> Creating cluster Connecting to node 127.0.0.1:6301: OK Connecting to node 127.0.0.1:6302: OK *** ERROR: Invalid configuration for cluster creation. *** Redis Cluster requires at least 3 master nodes. *** This is not possible with 2 nodes and 0 replicas per node. *** At least 3 nodes are required.
3台以上ないとダメらしい。
もっかい
[root@localhost redis]# ./src/redis-trib.rb create 127.0.0.1:6301 127.0.0.1:6302 127.0.0.1:6303 >>> Creating cluster Connecting to node 127.0.0.1:6301: OK Connecting to node 127.0.0.1:6302: OK Connecting to node 127.0.0.1:6303: OK >>> Performing hash slots allocation on 3 nodes... Using 3 masters: 127.0.0.1:6301 127.0.0.1:6302 127.0.0.1:6303 M: ec77ab685cc6ae9a8ebbf59de0da12d8537801c4 127.0.0.1:6301 slots:0-5460 (5461 slots) master M: b1eeb99149cc25514791474e445098d435b4215c 127.0.0.1:6302 slots:5461-10921 (5461 slots) master M: 65663be105a627ed06163c4e1ef95bbf997ce937 127.0.0.1:6303 slots:10922-16383 (5462 slots) master Can I set the above configuration? (type 'yes' to accept): yes >>> 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:6301) M: ec77ab685cc6ae9a8ebbf59de0da12d8537801c4 127.0.0.1:6301 slots:0-5460 (5461 slots) master M: b1eeb99149cc25514791474e445098d435b4215c 127.0.0.1:6302 slots:5461-10921 (5461 slots) master M: 65663be105a627ed06163c4e1ef95bbf997ce937 127.0.0.1:6303 slots:10922-16383 (5462 slots) master [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
無事できた?!てことで確認していきます。
redis-cliで接続する場合-cをつける必要があります。
[root@localhost redis]# redis-cli -c -p 6301 127.0.0.1:6301> cluster nodes b1eeb99149cc25514791474e445098d435b4215c 127.0.0.1:6302 master - 0 1387823588047 0 connected 5461-10921 ec77ab685cc6ae9a8ebbf59de0da12d8537801c4 :0 myself,master - 0 0 0 connected 0-5460 65663be105a627ed06163c4e1ef95bbf997ce937 127.0.0.1:6303 master - 0 1387823587037 0 connected 10922-16383
いけてるっぽい!
では続いて現状のコマンドが利用可能か確認していきます。
コマンド検証
SET/GET
Set
[root@localhost redis]# redis-cli -c -p 6301 127.0.0.1:6301> set key1 val1 -> Redirected to slot [9189] located at 127.0.0.1:6302 OK 127.0.0.1:6302>
接続先は6301でしたが、Set時にRedirectされるようです。
Redirect後は6302に接続されてますね。
Get
[root@localhost redis]# redis-cli -c -p 6303 127.0.0.1:6303> get key1 -> Redirected to slot [9189] located at 127.0.0.1:6302 "val1" 127.0.0.1:6302>
Setと同じですね。
実際の動作としてはクライアント(get)=>6303(6302にデータがあるという情報を返す)=>クライアント(get)=>6302といった感じのようです。
ただ無駄なリダイレクトが挟むので実際には、各クラスタのhash slotの情報を共有して対象のノードにデータをとりにいく感じになるのかな?
http://redis.io/presentation/Redis_Cluster.pdf
multi keysは公式に記載どおり使えませんでした、
127.0.0.1:6302> set key2 val2 -> Redirected to slot [4998] located at 127.0.0.1:6301 OK 127.0.0.1:6301> mget key1 key2 (error) ERR Multi keys request invalid in cluster
ちなみにhashは使えましたが、データ分散されませんでした。
Pub/Sub
では本命のPub/Subです。
6301ポートでsubscribe、6302からpublishしてみます。
pub(6302)
127.0.0.1:6302> PUBLISH room1 hogehoge (integer) 0
sub(6301)
[root@localhost ~]# redis-cli -c -p 6301 127.0.0.1:6301> SUBSCRIBE room1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "room1" 3) (integer) 1 1) "message" 2) "room1" 3) "hogehoge"
キター。まあいけるでしょうが・・・。
その他
その他のコマンドですが、全部試していないのでまた時間あるとき試してみます。
ただmonitorコマンドはClusterをサポートしていないみたい。
[root@localhost ~]# redis-cli -c -p 6302 127.0.0.1:6302> set key3 val3 -> Redirected to slot [935] located at 127.0.0.1:6301 OK 127.0.0.1:6301> set key4 val4 -> Redirected to slot [13120] located at 127.0.0.1:6303 OK 127.0.0.1:6303>
monitor
[root@localhost ~]# redis-cli -c -p 6301 monitor OK 1387824965.427047 [0 127.0.0.1:45907] "set" "key3" "val3"
ポート6301へのSetしかモニタリングされてない。
総評
今回、RedisClusterの動作を確認しましたが、サポートされていないコマンドが少しあったぐらいで普通にPub/Subを利用するぐらいであればいけそうです。
ただ、メインである耐障害性の検証は確認していないのでまた時間があるときにできたら書きます。てかそこやれよって感じですが・・・。
後、今回詳細には書きませんでしたが(書けよ)、redis-trib.rbでSlotの再配置コマンドを発行している最中にSetを1000/secぐらいで試していたらnilがいくつか返っておりクラスタのSlot内から外れていました。
実際に対象のポートにredis-cliの-cなしで接続すれば見れました。
というようなまだ不安定な箇所があるので、今は遊ぶぐらいですね。まだunstableやから当然か。
最後に!
すげー雑な感じになっちゃいましてすいません。
今回のRedisClusterのような分散データベースは検証してる分にはすごい楽しいのですが、実際運用するとなるとコストが高いのとConsistencyの部分が問題となるので本当に要件がマッチした時だけ使うのをおすすめします。
Redisとか保管すべきデータとか乗せちゃほんとダメ。後々きつい。
Cassandraとか・・・Cassandraとか・・・。
すごく長くなってしまいましたが、読んでいただいてありがとうございました!
また、誘ってくれたチャンタケ氏に感謝します。
明日は誰やろなー??