JedisSentinelPool now takes care of multi failover
* Now Pool.initPool() call closeInternalPool(), instead of destroy() ** calling destroy() in Pool.initPool() may have side effect, and JedisSentinelPool did * modify unit test to test failover twice (needs +1 slave) ** modify configurations for additional slave
This commit is contained in:
52
Makefile
52
Makefile
@@ -39,6 +39,17 @@ save ""
|
||||
appendonly no
|
||||
endef
|
||||
|
||||
define REDIS5_CONF
|
||||
daemonize yes
|
||||
port 6383
|
||||
requirepass foobared
|
||||
masterauth foobared
|
||||
pidfile /tmp/redis5.pid
|
||||
logfile /tmp/redis5.log
|
||||
save ""
|
||||
appendonly no
|
||||
endef
|
||||
|
||||
define REDIS_SENTINEL1
|
||||
port 26379
|
||||
daemonize yes
|
||||
@@ -82,6 +93,7 @@ export REDIS1_CONF
|
||||
export REDIS2_CONF
|
||||
export REDIS3_CONF
|
||||
export REDIS4_CONF
|
||||
export REDIS5_CONF
|
||||
export REDIS_SENTINEL1
|
||||
export REDIS_SENTINEL2
|
||||
export REDIS_SENTINEL3
|
||||
@@ -91,16 +103,18 @@ start:
|
||||
echo "$$REDIS2_CONF" | redis-server -
|
||||
echo "$$REDIS3_CONF" | redis-server -
|
||||
echo "$$REDIS4_CONF" | redis-server -
|
||||
echo "$$REDIS_SENTINEL1" | redis-sentinel -
|
||||
echo "$$REDIS_SENTINEL2" | redis-sentinel -
|
||||
echo "$$REDIS_SENTINEL3" | redis-sentinel -
|
||||
echo "$$REDIS5_CONF" | redis-server -
|
||||
echo "$$REDIS_SENTINEL1" | redis-server - --sentinel
|
||||
echo "$$REDIS_SENTINEL2" | redis-server - --sentinel
|
||||
echo "$$REDIS_SENTINEL3" | redis-server - --sentinel
|
||||
|
||||
stop:
|
||||
kill `cat /tmp/redis1.pid`
|
||||
kill `cat /tmp/redis2.pid`
|
||||
# this get's segfaulted by the tests
|
||||
kill `cat /tmp/redis3.pid` || true
|
||||
kill `cat /tmp/redis4.pid`
|
||||
kill `cat /tmp/redis4.pid` || true
|
||||
kill `cat /tmp/redis5.pid` || true
|
||||
kill `cat /tmp/sentinel1.pid`
|
||||
kill `cat /tmp/sentinel2.pid`
|
||||
kill `cat /tmp/sentinel3.pid`
|
||||
@@ -110,9 +124,10 @@ test:
|
||||
echo "$$REDIS2_CONF" | redis-server -
|
||||
echo "$$REDIS3_CONF" | redis-server -
|
||||
echo "$$REDIS4_CONF" | redis-server -
|
||||
echo "$$REDIS_SENTINEL1" | redis-sentinel -
|
||||
echo "$$REDIS_SENTINEL2" | redis-sentinel -
|
||||
echo "$$REDIS_SENTINEL3" | redis-sentinel -
|
||||
echo "$$REDIS5_CONF" | redis-server -
|
||||
echo "$$REDIS_SENTINEL1" | redis-server - --sentinel
|
||||
echo "$$REDIS_SENTINEL2" | redis-server - --sentinel
|
||||
echo "$$REDIS_SENTINEL3" | redis-server - --sentinel
|
||||
|
||||
mvn clean compile test
|
||||
|
||||
@@ -120,7 +135,8 @@ test:
|
||||
kill `cat /tmp/redis2.pid`
|
||||
# this get's segfaulted by the tests
|
||||
kill `cat /tmp/redis3.pid` || true
|
||||
kill `cat /tmp/redis4.pid`
|
||||
kill `cat /tmp/redis4.pid` || true
|
||||
kill `cat /tmp/redis5.pid` || true
|
||||
kill `cat /tmp/sentinel1.pid`
|
||||
kill `cat /tmp/sentinel2.pid`
|
||||
kill `cat /tmp/sentinel3.pid`
|
||||
@@ -130,9 +146,10 @@ deploy:
|
||||
echo "$$REDIS2_CONF" | redis-server -
|
||||
echo "$$REDIS3_CONF" | redis-server -
|
||||
echo "$$REDIS4_CONF" | redis-server -
|
||||
echo "$$REDIS_SENTINEL1" | redis-sentinel -
|
||||
echo "$$REDIS_SENTINEL2" | redis-sentinel -
|
||||
echo "$$REDIS_SENTINEL3" | redis-sentinel -
|
||||
echo "$$REDIS5_CONF" | redis-server -
|
||||
echo "$$REDIS_SENTINEL1" | redis-server - --sentinel
|
||||
echo "$$REDIS_SENTINEL2" | redis-server - --sentinel
|
||||
echo "$$REDIS_SENTINEL3" | redis-server - --sentinel
|
||||
|
||||
mvn clean deploy
|
||||
|
||||
@@ -140,7 +157,8 @@ deploy:
|
||||
kill `cat /tmp/redis2.pid`
|
||||
# this get's segfaulted by the tests
|
||||
kill `cat /tmp/redis3.pid` || true
|
||||
kill `cat /tmp/redis4.pid`
|
||||
kill `cat /tmp/redis4.pid` || true
|
||||
kill `cat /tmp/redis5.pid` || true
|
||||
kill `cat /tmp/sentinel1.pid`
|
||||
kill `cat /tmp/sentinel2.pid`
|
||||
kill `cat /tmp/sentinel3.pid`
|
||||
@@ -150,9 +168,10 @@ release:
|
||||
echo "$$REDIS2_CONF" | redis-server -
|
||||
echo "$$REDIS3_CONF" | redis-server -
|
||||
echo "$$REDIS4_CONF" | redis-server -
|
||||
echo "$$REDIS_SENTINEL1" | redis-sentinel -
|
||||
echo "$$REDIS_SENTINEL2" | redis-sentinel -
|
||||
echo "$$REDIS_SENTINEL3" | redis-sentinel -
|
||||
echo "$$REDIS5_CONF" | redis-server -
|
||||
echo "$$REDIS_SENTINEL1" | redis-server - --sentinel
|
||||
echo "$$REDIS_SENTINEL2" | redis-server - --sentinel
|
||||
echo "$$REDIS_SENTINEL3" | redis-server - --sentinel
|
||||
|
||||
mvn release:clean
|
||||
mvn release:prepare
|
||||
@@ -162,7 +181,8 @@ release:
|
||||
kill `cat /tmp/redis2.pid`
|
||||
# this get's segfaulted by the tests
|
||||
kill `cat /tmp/redis3.pid` || true
|
||||
kill `cat /tmp/redis4.pid`
|
||||
kill `cat /tmp/redis4.pid` || true
|
||||
kill `cat /tmp/redis5.pid` || true
|
||||
kill `cat /tmp/sentinel1.pid`
|
||||
kill `cat /tmp/sentinel2.pid`
|
||||
kill `cat /tmp/sentinel3.pid`
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -45,7 +45,7 @@
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<redis-hosts>localhost:6379,localhost:6380,localhost:6381,localhost:6382</redis-hosts>
|
||||
<redis-hosts>localhost:6379,localhost:6380,localhost:6381,localhost:6382,localhost:6383</redis-hosts>
|
||||
<sentinel-hosts>localhost:26379,localhost:26380</sentinel-hosts>
|
||||
<github.global.server>github</github.global.server>
|
||||
</properties>
|
||||
|
||||
@@ -24,7 +24,7 @@ public abstract class Pool<T> {
|
||||
|
||||
if (this.internalPool != null) {
|
||||
try {
|
||||
destroy();
|
||||
closeInternalPool();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,10 @@ public abstract class Pool<T> {
|
||||
returnResourceObject(resource);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
closeInternalPool();
|
||||
}
|
||||
|
||||
protected void returnBrokenResourceObject(final Object resource) {
|
||||
try {
|
||||
internalPool.invalidateObject(resource);
|
||||
@@ -68,8 +72,8 @@ public abstract class Pool<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
try {
|
||||
protected void closeInternalPool() {
|
||||
try {
|
||||
internalPool.close();
|
||||
} catch (Exception e) {
|
||||
throw new JedisException("Could not destroy the pool", e);
|
||||
|
||||
@@ -33,19 +33,24 @@ public class HostAndPortUtil {
|
||||
|
||||
HostAndPort defaulthnp5 = new HostAndPort();
|
||||
defaulthnp5.host = "localhost";
|
||||
defaulthnp5.port = Protocol.DEFAULT_SENTINEL_PORT;
|
||||
sentinelHostAndPortList.add(defaulthnp5);
|
||||
defaulthnp5.port = Protocol.DEFAULT_PORT + 4;
|
||||
redisHostAndPortList.add(defaulthnp5);
|
||||
|
||||
HostAndPort defaulthnp6 = new HostAndPort();
|
||||
defaulthnp6.host = "localhost";
|
||||
defaulthnp6.port = Protocol.DEFAULT_SENTINEL_PORT + 1;
|
||||
defaulthnp6.port = Protocol.DEFAULT_SENTINEL_PORT;
|
||||
sentinelHostAndPortList.add(defaulthnp6);
|
||||
|
||||
HostAndPort defaulthnp7 = new HostAndPort();
|
||||
defaulthnp7.host = "localhost";
|
||||
defaulthnp7.port = Protocol.DEFAULT_SENTINEL_PORT + 2;
|
||||
defaulthnp7.port = Protocol.DEFAULT_SENTINEL_PORT + 1;
|
||||
sentinelHostAndPortList.add(defaulthnp7);
|
||||
|
||||
HostAndPort defaulthnp8 = new HostAndPort();
|
||||
defaulthnp8.host = "localhost";
|
||||
defaulthnp8.port = Protocol.DEFAULT_SENTINEL_PORT + 2;
|
||||
sentinelHostAndPortList.add(defaulthnp8);
|
||||
|
||||
String envRedisHosts = System.getProperty("redis-hosts");
|
||||
String envSentinelHosts = System.getProperty("sentinel-hosts");
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ public class JedisSentinelPoolTest extends JedisTestBase {
|
||||
.get(2);
|
||||
protected static HostAndPort slave1 = HostAndPortUtil.getRedisServers()
|
||||
.get(3);
|
||||
protected static HostAndPort slave2 = HostAndPortUtil.getRedisServers()
|
||||
.get(4);
|
||||
protected static HostAndPort sentinel1 = HostAndPortUtil
|
||||
.getSentinelServers().get(1);
|
||||
protected static HostAndPort sentinel2 = HostAndPortUtil
|
||||
@@ -25,6 +27,9 @@ public class JedisSentinelPoolTest extends JedisTestBase {
|
||||
|
||||
protected static Jedis masterJedis;
|
||||
protected static Jedis slaveJedis1;
|
||||
protected static Jedis slaveJedis2;
|
||||
|
||||
protected static int slaveCount = 0;
|
||||
|
||||
protected Set<String> sentinels = new HashSet<String>();
|
||||
|
||||
@@ -39,37 +44,55 @@ public class JedisSentinelPoolTest extends JedisTestBase {
|
||||
slaveJedis1 = new Jedis(slave1.host, slave1.port);
|
||||
slaveJedis1.auth("foobared");
|
||||
slaveJedis1.slaveof(master.host, master.port);
|
||||
slaveCount++;
|
||||
|
||||
slaveJedis2 = new Jedis(slave2.host, slave2.port);
|
||||
slaveJedis2.auth("foobared");
|
||||
slaveJedis2.slaveof(master.host, master.port);
|
||||
slaveCount++;
|
||||
|
||||
sentinels.add(sentinel1.toString());
|
||||
sentinels.add(sentinel2.toString());
|
||||
|
||||
// FIXME: The following allows the master/slave relationship to
|
||||
// be established. We can do this more elegantly.
|
||||
// be established, and let sentinels know about this relationship.
|
||||
// We can do this more elegantly.
|
||||
Thread.sleep(10000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void segfaultMaster() throws InterruptedException {
|
||||
public void ensureSafeTwiceFailover() throws InterruptedException {
|
||||
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,
|
||||
new Config(), 1000, "foobared", 2);
|
||||
|
||||
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,
|
||||
new Config(), 1000, "foobared", 2);
|
||||
// perform failover
|
||||
doSegFaultMaster(pool);
|
||||
|
||||
Jedis jedis = pool.getResource();
|
||||
assertEquals("PONG", jedis.ping());
|
||||
// perform failover once again
|
||||
doSegFaultMaster(pool);
|
||||
|
||||
try {
|
||||
masterJedis.debug(DebugParams.SEGFAULT());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
// you can test failover as much as possible
|
||||
// but you need to prepare additional slave per failover
|
||||
}
|
||||
|
||||
// wait for the sentinel to promote a master
|
||||
// FIXME: we can query the sentinel and sleep
|
||||
// right until the master is promoted
|
||||
Thread.sleep(35000);
|
||||
private void doSegFaultMaster(JedisSentinelPool pool) throws InterruptedException {
|
||||
// jedis connection should be master
|
||||
Jedis jedis = pool.getResource();
|
||||
assertEquals("PONG", jedis.ping());
|
||||
|
||||
jedis = pool.getResource();
|
||||
assertEquals("PONG", jedis.ping());
|
||||
assertEquals("foobared", jedis.configGet("requirepass").get(1));
|
||||
assertEquals(2, jedis.getDB().intValue());
|
||||
try {
|
||||
jedis.debug(DebugParams.SEGFAULT());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
// wait for the sentinel to promote a master
|
||||
// FIXME: we can query the sentinel and sleep
|
||||
// right until the master is promoted
|
||||
Thread.sleep(35000);
|
||||
|
||||
jedis = pool.getResource();
|
||||
assertEquals("PONG", jedis.ping());
|
||||
assertEquals("foobared", jedis.configGet("requirepass").get(1));
|
||||
assertEquals(2, jedis.getDB().intValue());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user