Merge branch 'master' of https://github.com/nrodrigues/jedis into nrodrigues-master

This commit is contained in:
Jungtaek Lim
2014-09-11 10:52:29 +09:00
7 changed files with 97 additions and 37 deletions

View File

@@ -1,5 +1,7 @@
package redis.clients.jedis;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
@@ -8,8 +10,7 @@ import org.apache.commons.pool2.impl.DefaultPooledObject;
* PoolableObjectFactory custom impl.
*/
class JedisFactory implements PooledObjectFactory<Jedis> {
private final String host;
private final int port;
private final AtomicReference<HostAndPort> hostAndPort = new AtomicReference<HostAndPort>();
private final int timeout;
private final String password;
private final int database;
@@ -23,14 +24,17 @@ class JedisFactory implements PooledObjectFactory<Jedis> {
public JedisFactory(final String host, final int port, final int timeout,
final String password, final int database, final String clientName) {
super();
this.host = host;
this.port = port;
this.hostAndPort.set(new HostAndPort(host, port));
this.timeout = timeout;
this.password = password;
this.database = database;
this.clientName = clientName;
}
public void setHostAndPort(final HostAndPort hostAndPort) {
this.hostAndPort.set(hostAndPort);
}
@Override
public void activateObject(PooledObject<Jedis> pooledJedis)
throws Exception {
@@ -60,7 +64,8 @@ class JedisFactory implements PooledObjectFactory<Jedis> {
@Override
public PooledObject<Jedis> makeObject() throws Exception {
final Jedis jedis = new Jedis(this.host, this.port, this.timeout);
final HostAndPort hostAndPort = this.hostAndPort.get();
final Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort(), this.timeout);
jedis.connect();
if (null != this.password) {
@@ -86,7 +91,13 @@ class JedisFactory implements PooledObjectFactory<Jedis> {
public boolean validateObject(PooledObject<Jedis> pooledJedis) {
final BinaryJedis jedis = pooledJedis.getObject();
try {
return jedis.isConnected() && jedis.ping().equals("PONG");
HostAndPort hostAndPort = this.hostAndPort.get();
String connectionHost = jedis.getClient().getHost();
int connectionPort = jedis.getClient().getPort();
return hostAndPort.getHost().equals(connectionHost) && hostAndPort.getPort() == connectionPort &&
jedis.isConnected() && jedis.ping().equals("PONG");
} catch (final Exception e) {
return false;
}

View File

@@ -65,6 +65,7 @@ public class JedisSentinelPool extends Pool<Jedis> {
public JedisSentinelPool(String masterName, Set<String> sentinels,
final GenericObjectPoolConfig poolConfig, int timeout,
final String password, final int database) {
this.poolConfig = poolConfig;
this.timeout = timeout;
this.password = password;
@@ -74,6 +75,7 @@ public class JedisSentinelPool extends Pool<Jedis> {
initPool(master);
}
private volatile JedisFactory factory;
private volatile HostAndPort currentHostMaster;
public void destroy() {
@@ -91,10 +93,18 @@ public class JedisSentinelPool extends Pool<Jedis> {
private void initPool(HostAndPort master) {
if (!master.equals(currentHostMaster)) {
currentHostMaster = master;
if (factory == null) {
factory = new JedisFactory(master.getHost(), master.getPort(),
timeout, password, database);
initPool(poolConfig, factory);
} else {
factory.setHostAndPort(currentHostMaster);
// although we clear the pool, we still have to check the returned object
// in getResource, this call only clears idle instances, not borrowed instances
internalPool.clear();
}
log.info("Created JedisPool to master at " + master);
initPool(poolConfig,
new JedisFactory(master.getHost(), master.getPort(),
timeout, password, database));
}
}
@@ -115,19 +125,23 @@ public class JedisSentinelPool extends Pool<Jedis> {
log.fine("Connecting to Sentinel " + hap);
Jedis jedis = null;
try {
Jedis jedis = new Jedis(hap.getHost(), hap.getPort());
jedis = new Jedis(hap.getHost(), hap.getPort());
if (master == null) {
master = toHostAndPort(jedis
.sentinelGetMasterAddrByName(masterName));
log.fine("Found Redis master at " + master);
jedis.disconnect();
break outer;
}
} catch (JedisConnectionException e) {
log.warning("Cannot connect to sentinel running @ " + hap
+ ". Trying next one.");
} finally {
if (jedis != null) {
jedis.close();
}
}
}
@@ -164,9 +178,22 @@ public class JedisSentinelPool extends Pool<Jedis> {
@Override
public Jedis getResource() {
Jedis jedis = super.getResource();
jedis.setDataSource(this);
return jedis;
while (true) {
Jedis jedis = super.getResource();
jedis.setDataSource(this);
// get a reference because it can change concurrently
final HostAndPort master = currentHostMaster;
final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(),
jedis.getClient().getPort());
if (master.equals(connection)) {
// connected to the correct master
return jedis;
} else {
returnBrokenResource(jedis);
}
}
}
public void returnBrokenResource(final Jedis resource) {
@@ -304,4 +331,4 @@ public class JedisSentinelPool extends Pool<Jedis> {
}
}
}
}
}