关于 Redis Cluster 模式下获取 Java Client 的问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lin_wj1995/article/details/79960942

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);
    }
}

各位有什么更好的想法或者问题可以提出来讨论讨论。。

阅读更多

没有更多推荐了,返回首页