Redis连接池对于单机模式来说,官网有提供个JedisPool工具类,用起来也比较方便
但是对于Redis集群模式下,官网没有提供连接池的工具类,于是就需要我们自己来实现类似的功能了,我这里采用的是单例模式的方法来解决高并发的场景。
单机模式
如果对于 Redis 是单机模式下的话,那么 Redis 有提供一个JedisPool
类 用来构建 Redis Client 的连接池,非常方便,简单代码如下:
JedisPoolConfig config = new JedisPoolConfig();
//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
config.setMaxIdle(5);
//控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
config.setMaxTotal(1000 * 100);
//表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
config.setMaxWaitMillis(30);
config.setTestOnBorrow(true);
config.setTestOnReturn(true);
//如果你遇到 java.net.SocketTimeoutException: Read timed out exception的异常信息,请尝试在构造JedisPool的时候设置自己的超时值. JedisPool默认的超时时间是2秒(单位毫秒)
pool = new JedisPool(config, "127.0.0.1", 6379);
/*
* 获得jedis连接
*/
Jedis jedis = pool.getResource();
集群模式
单机模式Redis官方有提供JedisPool类,用起来非常方便。
但是,如果Redis部署的是集群模式,你会发现,官方根本就没有提供集群模式下的连接池的类!!
官方有提供一个JedisClsuter
的客户端类。但是如果在高并发的情况下,每要处理一次就新建一个JedisCluster,那么显然这种方式是不可取的!
那么问题来了,Redis集群模式应该如何解决高并发的场景呢?
咦,这是我想到了一个自己感觉很不错的方法,就是采用单例模式,简单的代码如下:
public class JedisClsuterUtil {
private static JedisCluster jedis = null;
private JedisClsuterUtil(){}
public static JedisCluster getJedis(){
if(jedis==null){
synchronized(JedisClsuterUtil.class){
if(jedis==null){
Set<HostAndPort> hostAndPortSet = new HashSet();
hostAndPortSet.add(new HostAndPort("host1", 9001));
hostAndPortSet.add(new HostAndPort("host2", 9002));
// ....
jedis = new JedisCluster(hostAndPortSet);
}
}
}
return jedis;
}
}
用该方法测试过,是没有问题的。
改进:
上面是依靠double-checked locking的,这是一种不正确的用法,并不能达到预期目标。
所以以下是单例模式的改进版:
public class JedisClsuterUtil {
private JedisClsuterUtil(){}
public static JedisCluster getJedis(){
return JedisClusterHolder.jedis;
}
private static class JedisClusterHolder{
private static Set<HostAndPort> hostAndPortSet;
static {
hostAndPortSet = new HashSet();
hostAndPortSet.add(new HostAndPort("host1", 9001));
hostAndPortSet.add(new HostAndPort("host2", 9002));
}
private static JedisCluster jedis = new JedisCluster(hostAndPortSet);
}
}
各位有什么更好的想法或者问题可以提出来讨论讨论。。