An easy way to test Redis Cluster is either to try any of the above clients or simply theredis-cli command line utility. The following is an example of interaction using the latter:
$ redis-cli -c -p 7000 redis 127.0.0.1:7000> set foo bar -> Redirected to slot [12182] located at 127.0.0.1:7002 OK redis 127.0.0.1:7002> set hello world -> Redirected to slot [866] located at 127.0.0.1:7000 OK redis 127.0.0.1:7000> get foo -> Redirected to slot [12182] located at 127.0.0.1:7002 "bar" redis 127.0.0.1:7000> get hello -> Redirected to slot [866] located at 127.0.0.1:7000 "world"
Note: if you created the cluster using the script your nodes may listen to different ports, starting from 30001 by default.
The redis-cli cluster support is very basic so it always uses the fact that Redis Cluster nodes are able to redirect a client to the right node. A serious client is able to do better than that, and cache the map between hash slots and nodes addresses, to directly use the right connection to the right node. The map is refreshed only when something changed in the cluster configuration, for example after a failover or after the system administrator changed the cluster layout by adding or removing nodes.
*Writing an example app with redis-rb-cluster
Before going forward showing how to operate the Redis Cluster, doing things like a failover, or a resharding, we need to create some example application or at least to be able to understand the semantics of a simple Redis Cluster client interaction.
In this way we can run an example and at the same time try to make nodes failing, or start a resharding, to see how Redis Cluster behaves under real world conditions. It is not very helpful to see what happens while nobody is writing to the cluster.
This section explains some basic usage of redis-rb-cluster showing two examples. The first is the following, and is theexample.rb file inside the redis-rb-cluster distribution:
1 require './cluster'
2
3 startup_nodes = [
4 {:host => "127.0.0.1", :port => 7000},
5 {:host => "127.0.0.1", :port => 7001}
6 ]
7 rc = RedisCluster.new(startup_nodes,32,:timeout => 0.1)
8
9 last = false
10
11 while not last
12 begin
13 last = rc.get("__last__")
14 last = 0 if !last
15 rescue => e
16 puts "error #{e.to_s}"
17 sleep 1
18 end
19 end
20
21 ((last.to_i+1)..1000000000).each{|x|
22 begin
23 rc.set("foo#{x}",x)
24 puts rc.get("foo#{x}")
25 rc.set("__last__",x)
26 rescue => e
27 puts "error #{e.to_s}"
28 end
29 sleep 0.1
30 }
The application does a very simple thing, it sets keys in the form foo
SET foo0 0 SET foo1 1 SET foo2 2 And so forth...
The program looks more complex than it should usually as it is designed to show errors on the screen instead of exiting with an exception, so every operation performed with the cluster is wrapped bybeginrescue blocks.
The line 7 is the first interesting line in the program. It creates the Redis Cluster object, using as argument a list ofstartup nodes, the maximum number of connections this object is allowed to take against different nodes, and finally the timeout after a given operation is considered to be failed.
The startup nodes don't need to be