Edited at

RedisのCluster構成でPubSubを試す

More than 3 years have passed since last update.


Redisをクラスタ構成で動かす

構築メモにて。


環境


  • Ubuntu 14.04


実験

redis-cliでいろいろ実験してみる。なお、redis-cliに、-cオプションをつけないと、値の設定や取得でエラーになる。(-cはクラスタモード。)

-cをつけずに値の設定や取得を行うと、以下のようなエラーになる。

127.0.0.1:7000> set key1 100

(error) MOVED 9189 127.0.0.1:7001
127.0.0.1:7000> get key1
(error) MOVED 9189 127.0.0.1:7001


GET/SET

key1に値100を設定してみた。

key1は、ハッシュスロット9189に保存されたようだ。Redisが自動的に振り分けて7001のノードにリダイレクトしている。

127.0.0.1:7000> set key1 100

-> Redirected to slot [9189] located at 127.0.0.1:7001
OK
127.0.0.1:7001> get key1
"100"


MGET

今度は、MGETで複数の値を取得してみる。

まずは新たに値key2:200を追加する。すると、今度は7000のノードに保存した。

127.0.0.1:7001> set key2 200

-> Redirected to slot [4998] located at 127.0.0.1:7000
OK
127.0.0.1:7000> get key2
"200"

この時点で、key17001のノードに、key2のノードは7000のノードに保存されている。この状態で、MGETを実行して正常に取得できるか?

実行してみると、スロットを跨いで取得することは出来ない。

127.0.0.1:7001> mget key1 key2

(error) CROSSSLOT Keys in request don't hash to the same slot

では、どのようにすればMGETすることが出来るようになるか?ここで、ハッシュタグの出番。ハッシュタグとは、キーに{foo}のようにブラケットで囲んだ文字列を付与することにより、同じハッシュスロットに割り当てる機能である。

では実際にやってみるとどうなるか?以下は、{tag}というハッシュタグを、key1/key2に付与してMGETしてみる。

正常に動作しているようである。

127.0.0.1:7001> set {tag}key1 1000

OK
127.0.0.1:7001> get {tag}key1
"1000"
127.0.0.1:7001> set {tag}key2 2000
OK
127.0.0.1:7001> get {tag}key2
"2000"
127.0.0.1:7001> mget {tag}key1 {tag}key2
1) "1000"
2) "2000"

では、ハッシュタグ{tag}を付与した値が保存されたノードは7001であるが、7000のノードで、{tag}を付与した値をSETするとどうなるか?

7001のノードにリダイレクトした後、SETしてくれている。

127.0.0.1:7000> set {tag}key3 3000

-> Redirected to slot [8338] located at 127.0.0.1:7001
OK

このように、ハッシュタグを付与した値は、同じノードに対してSETしてくれることがわかった。

MGETなどのように、複数のキーに対して何かを行うようなコマンドを使う場合は、予めハッシュタグを考慮して設計する必要がありそうだ。


Pub/Sub


同じノードでPub/Sub

まずは簡単に、同一ノードに接続したPublisherとSubscriberで正常に動作するか確認してみる。以下のコマンドを2つターミナルを立ち上げ実行する。


  • Subscriber

127.0.0.1:7000> SUBSCRIBE 'channel:7000'

Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel:7000"
3) (integer) 1


  • Publisher

127.0.0.1:7000> PUBLISH 'channel:7000' 'Hello from 7000'

(integer) 1

結果、Subscriberに正常に通知された。

127.0.0.1:7000> SUBSCRIBE 'channel:7000'

(snip)
1) "message"
2) "channel:7000"
3) "Hello from 7000"


異なるノードでPub/Sub

今度は、Publisherを異なるノードに接続し、Publishしてみる。

127.0.0.1:7001> PUBLISH 'channel:7000' 'Hello from 7001'

(integer) 0
127.0.0.1:7001>

結果、Subscriberに正常に通知された。

127.0.0.1:7000> SUBSCRIBE 'channel:7000'

(snip)
1) "message"
2) "channel:7000"
3) "Hello from 7001"


PubをSlaveに接続してPub/Sub

今度は、Publisherをスレーブに接続してPublishしてみる。

127.0.0.1:7004> PUBLISH 'channel:7000' 'Hello from 7004'

(integer) 0

結果、Subscriberに正常に通知された。

127.0.0.1:7000> SUBSCRIBE 'channel:7000'

(snip)
1) "message"
2) "channel:7000"
3) "Hello from 7004"


アクティブなチャネル一覧の取得

PUBSUB CHANNELS [pattern]で、アクティブなチャネル一覧を取得できるが、クラスタ環境で取得可能か確かめる。

Subscriberは、7000でチャネルchannel:7000をSubscribeしている状態である。

127.0.0.1:7000> SUBSCRIBE 'channel:7000'

Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel:7000"
3) (integer) 1

まずは同じノードから。正常に取得できた。

127.0.0.1:7000> PUBSUB CHANNELS 'channel:7000'

1) "channel:7000"

次に、異なるノード7001から。取得できない。

どうやら、PUBSUB CHANNELSは、PubとSubが異なるノードの場合、期待通りに動作しないようだ。

127.0.0.1:7001> PUBSUB CHANNELS 'channel:7000'

(empty list or set)

ちなみに、ハッシュタグをつけても無駄である。


アクティブなチャネル数の取得

PUBSUB NUMSUB [channel]で、アクティブなチャネル数を取得することが出来るが、クラスタ環境で正常に動作するか試す。PUBSUB CHANNELSの場合と同様、7000のノードでSUBしている状態で試した。

まずは同じノードから。正常に取得できた。

127.0.0.1:7000> PUBSUB NUMSUB 'channel:7000'

1) "channel:7000"
2) (integer) 1

次に、異なるノードから。取得できない。

127.0.0.1:7001> PUBSUB NUMSUB 'channel:7000'

1) "channel:7000"
2) (integer) 0

ちなみに、ハッシュタグをつけても無駄である。