diff --git a/Makefile b/Makefile
index 21eaa2b..e0189f2 100644
--- a/Makefile
+++ b/Makefile
@@ -61,6 +61,7 @@ save ""
appendonly no
endef
+# SENTINELS
define REDIS_SENTINEL1
port 26379
daemonize yes
@@ -97,6 +98,40 @@ pidfile /tmp/sentinel3.pid
logfile /tmp/sentinel3.log
endef
+# CLUSTER REDIS NODES
+define REDIS_CLUSTER_NODE1_CONF
+daemonize yes
+port 7379
+pidfile /tmp/redis_cluster_node1.pid
+logfile /tmp/redis_cluster_node1.log
+save ""
+appendonly no
+cluster-enabled yes
+cluster-config-file /tmp/redis_cluster_node1.conf
+endef
+
+define REDIS_CLUSTER_NODE2_CONF
+daemonize yes
+port 7380
+pidfile /tmp/redis_cluster_node2.pid
+logfile /tmp/redis_cluster_node2.log
+save ""
+appendonly no
+cluster-enabled yes
+cluster-config-file /tmp/redis_cluster_node2.conf
+endef
+
+define REDIS_CLUSTER_NODE3_CONF
+daemonize yes
+port 7381
+pidfile /tmp/redis_cluster_node3.pid
+logfile /tmp/redis_cluster_node3.log
+save ""
+appendonly no
+cluster-enabled yes
+cluster-config-file /tmp/redis_cluster_node3.conf
+endef
+
export REDIS1_CONF
export REDIS2_CONF
export REDIS3_CONF
@@ -106,6 +141,9 @@ export REDIS6_CONF
export REDIS_SENTINEL1
export REDIS_SENTINEL2
export REDIS_SENTINEL3
+export REDIS_CLUSTER_NODE1_CONF
+export REDIS_CLUSTER_NODE2_CONF
+export REDIS_CLUSTER_NODE3_CONF
start:
echo "$$REDIS1_CONF" | redis-server -
@@ -119,6 +157,9 @@ start:
echo "$$REDIS_SENTINEL2" > /tmp/sentinel2.conf && redis-server /tmp/sentinel2.conf --sentinel
@sleep 0.5
echo "$$REDIS_SENTINEL3" > /tmp/sentinel3.conf && redis-server /tmp/sentinel3.conf --sentinel
+ echo "$$REDIS_CLUSTER_NODE1_CONF" | redis-server -
+ echo "$$REDIS_CLUSTER_NODE2_CONF" | redis-server -
+ echo "$$REDIS_CLUSTER_NODE3_CONF" | redis-server -
stop:
kill `cat /tmp/redis1.pid`
@@ -131,6 +172,12 @@ stop:
kill `cat /tmp/sentinel1.pid`
kill `cat /tmp/sentinel2.pid`
kill `cat /tmp/sentinel3.pid`
+ kill `cat /tmp/redis_cluster_node1.pid` || true
+ kill `cat /tmp/redis_cluster_node2.pid` || true
+ kill `cat /tmp/redis_cluster_node3.pid` || true
+ rm -f /tmp/redis_cluster_node1.conf
+ rm -f /tmp/redis_cluster_node2.conf
+ rm -f /tmp/redis_cluster_node3.conf
test:
make start
diff --git a/pom.xml b/pom.xml
index 9409ec9..f6575eb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,6 +47,7 @@
localhost:6379,localhost:6380,localhost:6381,localhost:6382,localhost:6383,localhost:6384
localhost:26379,localhost:26380,localhost:26381
+ localhost:7379,localhost:7380,localhost:7381
github
diff --git a/src/main/java/redis/clients/jedis/BinaryClient.java b/src/main/java/redis/clients/jedis/BinaryClient.java
index acb120b..1b9db49 100644
--- a/src/main/java/redis/clients/jedis/BinaryClient.java
+++ b/src/main/java/redis/clients/jedis/BinaryClient.java
@@ -1100,4 +1100,9 @@ public class BinaryClient extends Connection {
public void hincrByFloat(final byte[] key, final byte[] field, double increment) {
sendCommand(HINCRBYFLOAT, key, field, toByteArray(increment));
}
+
+ public void cluster(final byte[]... args) {
+ sendCommand(CLUSTER, args);
+ }
+
}
diff --git a/src/main/java/redis/clients/jedis/Client.java b/src/main/java/redis/clients/jedis/Client.java
index 9c97e38..b726821 100644
--- a/src/main/java/redis/clients/jedis/Client.java
+++ b/src/main/java/redis/clients/jedis/Client.java
@@ -807,4 +807,12 @@ public class Client extends BinaryClient implements Commands {
public void hincrByFloat(final String key, final String field, double increment) {
hincrByFloat(SafeEncoder.encode(key), SafeEncoder.encode(field), increment);
}
+
+ public void cluster(final String... args) {
+ final byte[][] arg = new byte[args.length][];
+ for (int i = 0; i < arg.length; i++) {
+ arg[i] = SafeEncoder.encode(args[i]);
+ }
+ cluster(arg);
+ }
}
diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java
index 23cfd3d..d2daca5 100644
--- a/src/main/java/redis/clients/jedis/Jedis.java
+++ b/src/main/java/redis/clients/jedis/Jedis.java
@@ -3076,4 +3076,10 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
String relpy = client.getBulkReply();
return (relpy != null ? new Double(relpy) : null);
}
+
+ public String clusterNodes() {
+ checkIsInMulti();
+ client.cluster(Protocol.CLUSTER_NODES);
+ return client.getBulkReply();
+ }
}
diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java
index f85c324..e4a9126 100644
--- a/src/main/java/redis/clients/jedis/Protocol.java
+++ b/src/main/java/redis/clients/jedis/Protocol.java
@@ -30,6 +30,8 @@ public final class Protocol {
public static final String SENTINEL_RESET = "reset";
public static final String SENTINEL_SLAVES = "slaves";
+ public static final String CLUSTER_NODES = "nodes";
+
private Protocol() {
// this prevent the class from instantiation
}
@@ -155,7 +157,7 @@ public final class Protocol {
public static enum Command {
PING, SET, GET, QUIT, EXISTS, DEL, TYPE, FLUSHDB, KEYS, RANDOMKEY, RENAME, RENAMENX, RENAMEX, DBSIZE, EXPIRE, EXPIREAT, TTL, SELECT, MOVE, FLUSHALL, GETSET, MGET, SETNX, SETEX, MSET, MSETNX, DECRBY, DECR, INCRBY, INCR, APPEND, SUBSTR, HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, RPUSH, LPUSH, LLEN, LRANGE, LTRIM, LINDEX, LSET, LREM, LPOP, RPOP, RPOPLPUSH, SADD, SMEMBERS, SREM, SPOP, SMOVE, SCARD, SISMEMBER, SINTER, SINTERSTORE, SUNION, SUNIONSTORE, SDIFF, SDIFFSTORE, SRANDMEMBER, ZADD, ZRANGE, ZREM, ZINCRBY, ZRANK, ZREVRANK, ZREVRANGE, ZCARD, ZSCORE, MULTI, DISCARD, EXEC, WATCH, UNWATCH, SORT, BLPOP, BRPOP, AUTH, SUBSCRIBE, PUBLISH, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, ZCOUNT, ZRANGEBYSCORE, ZREVRANGEBYSCORE, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZUNIONSTORE, ZINTERSTORE, SAVE, BGSAVE, BGREWRITEAOF, LASTSAVE, SHUTDOWN, INFO, MONITOR, SLAVEOF, CONFIG, STRLEN, SYNC, LPUSHX, PERSIST, RPUSHX, ECHO, LINSERT, DEBUG, BRPOPLPUSH, SETBIT, GETBIT, SETRANGE, GETRANGE, EVAL, EVALSHA, SCRIPT, SLOWLOG, OBJECT, BITCOUNT, BITOP, SENTINEL,
- DUMP, RESTORE, PEXPIRE, PEXPIREAT, PTTL, INCRBYFLOAT, PSETEX, CLIENT, TIME, MIGRATE, HINCRBYFLOAT;
+ DUMP, RESTORE, PEXPIRE, PEXPIREAT, PTTL, INCRBYFLOAT, PSETEX, CLIENT, TIME, MIGRATE, HINCRBYFLOAT, CLUSTER;
public final byte[] raw;
diff --git a/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java b/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java
index be64c53..c7be599 100644
--- a/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java
+++ b/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java
@@ -9,83 +9,106 @@ import redis.clients.jedis.Protocol;
public class HostAndPortUtil {
private static List redisHostAndPortList = new ArrayList();
private static List sentinelHostAndPortList = new ArrayList();
+ private static List clusterHostAndPortList = new ArrayList();
static {
-
- HostAndPort defaulthnp1 = new HostAndPort("localhost", Protocol.DEFAULT_PORT);
- redisHostAndPortList.add(defaulthnp1);
- HostAndPort defaulthnp2 = new HostAndPort("localhost", Protocol.DEFAULT_PORT + 1);
- redisHostAndPortList.add(defaulthnp2);
-
- HostAndPort defaulthnp3 = new HostAndPort("localhost", Protocol.DEFAULT_PORT + 2);
- redisHostAndPortList.add(defaulthnp3);
-
- HostAndPort defaulthnp4 = new HostAndPort("localhost", Protocol.DEFAULT_PORT + 3);
- redisHostAndPortList.add(defaulthnp4);
-
- HostAndPort defaulthnp5 = new HostAndPort("localhost", Protocol.DEFAULT_PORT + 4);
- redisHostAndPortList.add(defaulthnp5);
-
- HostAndPort defaulthnp6 = new HostAndPort("localhost", Protocol.DEFAULT_PORT + 5);
- redisHostAndPortList.add(defaulthnp6);
-
- HostAndPort defaulthnp7 = new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT);
- sentinelHostAndPortList.add(defaulthnp7);
-
- HostAndPort defaulthnp8 = new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT + 1);
- sentinelHostAndPortList.add(defaulthnp8);
-
- HostAndPort defaulthnp9 = new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT + 2);
- sentinelHostAndPortList.add(defaulthnp9);
+ HostAndPort defaulthnp1 = new HostAndPort("localhost",
+ Protocol.DEFAULT_PORT);
+ redisHostAndPortList.add(defaulthnp1);
- String envRedisHosts = System.getProperty("redis-hosts");
- String envSentinelHosts = System.getProperty("sentinel-hosts");
-
- redisHostAndPortList = parseHosts(envRedisHosts, redisHostAndPortList);
- sentinelHostAndPortList = parseHosts(envSentinelHosts, sentinelHostAndPortList);
+ HostAndPort defaulthnp2 = new HostAndPort("localhost",
+ Protocol.DEFAULT_PORT + 1);
+ redisHostAndPortList.add(defaulthnp2);
+
+ HostAndPort defaulthnp3 = new HostAndPort("localhost",
+ Protocol.DEFAULT_PORT + 2);
+ redisHostAndPortList.add(defaulthnp3);
+
+ HostAndPort defaulthnp4 = new HostAndPort("localhost",
+ Protocol.DEFAULT_PORT + 3);
+ redisHostAndPortList.add(defaulthnp4);
+
+ HostAndPort defaulthnp5 = new HostAndPort("localhost",
+ Protocol.DEFAULT_PORT + 4);
+ redisHostAndPortList.add(defaulthnp5);
+
+ HostAndPort defaulthnp6 = new HostAndPort("localhost",
+ Protocol.DEFAULT_PORT + 5);
+ redisHostAndPortList.add(defaulthnp6);
+
+ HostAndPort defaulthnp7 = new HostAndPort("localhost",
+ Protocol.DEFAULT_SENTINEL_PORT);
+ sentinelHostAndPortList.add(defaulthnp7);
+
+ HostAndPort defaulthnp8 = new HostAndPort("localhost",
+ Protocol.DEFAULT_SENTINEL_PORT + 1);
+ sentinelHostAndPortList.add(defaulthnp8);
+
+ HostAndPort defaulthnp9 = new HostAndPort("localhost",
+ Protocol.DEFAULT_SENTINEL_PORT + 2);
+ sentinelHostAndPortList.add(defaulthnp9);
+
+ clusterHostAndPortList.add(new HostAndPort("localhost", 7379));
+ clusterHostAndPortList.add(new HostAndPort("localhost", 7380));
+ clusterHostAndPortList.add(new HostAndPort("localhost", 7381));
+
+ String envRedisHosts = System.getProperty("redis-hosts");
+ String envSentinelHosts = System.getProperty("sentinel-hosts");
+ String envClusterHosts = System.getProperty("cluster-hosts");
+
+ redisHostAndPortList = parseHosts(envRedisHosts, redisHostAndPortList);
+ sentinelHostAndPortList = parseHosts(envSentinelHosts,
+ sentinelHostAndPortList);
+ clusterHostAndPortList = parseHosts(envClusterHosts,
+ clusterHostAndPortList);
}
- public static List parseHosts(String envHosts, List existingHostsAndPorts) {
-
- if (null != envHosts && 0 < envHosts.length()) {
-
- String[] hostDefs = envHosts.split(",");
-
- if (null != hostDefs && 2 <= hostDefs.length) {
-
- List envHostsAndPorts = new ArrayList(hostDefs.length);
-
- for (String hostDef : hostDefs) {
-
- String[] hostAndPort = hostDef.split(":");
-
- if (null != hostAndPort && 2 == hostAndPort.length) {
- String host = hostAndPort[0];
- int port = Protocol.DEFAULT_PORT;
-
- try {
- port = Integer.parseInt(hostAndPort[1]);
- } catch (final NumberFormatException nfe) {
- }
-
- envHostsAndPorts.add(new HostAndPort(host, port));
- }
- }
-
- return envHostsAndPorts;
- }
- }
-
- return existingHostsAndPorts;
+ public static List parseHosts(String envHosts,
+ List existingHostsAndPorts) {
+
+ if (null != envHosts && 0 < envHosts.length()) {
+
+ String[] hostDefs = envHosts.split(",");
+
+ if (null != hostDefs && 2 <= hostDefs.length) {
+
+ List envHostsAndPorts = new ArrayList(
+ hostDefs.length);
+
+ for (String hostDef : hostDefs) {
+
+ String[] hostAndPort = hostDef.split(":");
+
+ if (null != hostAndPort && 2 == hostAndPort.length) {
+ String host = hostAndPort[0];
+ int port = Protocol.DEFAULT_PORT;
+
+ try {
+ port = Integer.parseInt(hostAndPort[1]);
+ } catch (final NumberFormatException nfe) {
+ }
+
+ envHostsAndPorts.add(new HostAndPort(host, port));
+ }
+ }
+
+ return envHostsAndPorts;
+ }
+ }
+
+ return existingHostsAndPorts;
}
-
+
public static List getRedisServers() {
- return redisHostAndPortList;
- }
-
- public static List getSentinelServers() {
- return sentinelHostAndPortList;
+ return redisHostAndPortList;
}
+ public static List getSentinelServers() {
+ return sentinelHostAndPortList;
+ }
+
+ public static List getClusterServers() {
+ return clusterHostAndPortList;
+ }
}
diff --git a/src/test/java/redis/clients/jedis/tests/commands/ClusterCommandsTest.java b/src/test/java/redis/clients/jedis/tests/commands/ClusterCommandsTest.java
new file mode 100644
index 0000000..1599b02
--- /dev/null
+++ b/src/test/java/redis/clients/jedis/tests/commands/ClusterCommandsTest.java
@@ -0,0 +1,41 @@
+package redis.clients.jedis.tests.commands;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.tests.HostAndPortUtil;
+import redis.clients.jedis.tests.JedisTestBase;
+
+public class ClusterCommandsTest extends JedisTestBase {
+ private Jedis node1;
+ private Jedis node2;
+
+ @Before
+ public void setUp() throws Exception {
+ HostAndPort nodeInfo1 = HostAndPortUtil.getClusterServers().get(0);
+ HostAndPort nodeInfo2 = HostAndPortUtil.getClusterServers().get(1);
+
+ node1 = new Jedis(nodeInfo1.getHost(), nodeInfo1.getPort());
+ node1.connect();
+ node1.flushAll();
+
+ node2 = new Jedis(nodeInfo2.getHost(), nodeInfo2.getPort());
+ node2.connect();
+ node2.flushAll();
+ }
+
+ @After
+ public void tearDown() {
+ node1.disconnect();
+ node2.disconnect();
+ }
+
+ @Test
+ public void clusterNodes() {
+ String nodes = node1.clusterNodes();
+ assertEquals(1, nodes.split("\n").length);
+ }
+}
\ No newline at end of file