zoukankan      html  css  js  c++  java
  • Redis Cluster集群搭建后,客户端的连接研究(Spring/Jedis)(待实践)

    说明:无论是否已经搭建好集群,还是使用什么样的客户端去连接,都是必须把全部IP列表集成进去,然后随机往其中一个IP写。

    这样做的好处:

    1、随机IP写入之后,Redis Cluster代理层会自动根据分片写入其中一台,随机IP只是减缓一个IP时的巨大流量问题。

    2、对于写死的IP问题,可以通过动态配置文件或者接口,观察IP更新或者节点增加时,重新实例化,原有业务不影响,因为对象本身到GC时也代表当前业务已经完成。

    下面是基于Spring和Jedis实现的集群,同时后端采用就是Redis Cluster原生集群。

    当然,也可以自己手写这些客户端等。

    原理还待研究,到底是不是只要写上了这些IP,客户端就全部保持着这些连接,然后有助于判断哪个不可用。

    还有一种想法是通过HAProxy来聚合出一个IP,然后将这些IP都添加进去,不过没测试过这种方式对Redis Cluster模式会不会有影响。

    我猜测客户端需要全部IP都写上,是由于其支持-MOVED 6918 127.0.0.1:7004这样的命令,去取数据。应该是客户端实现了这些协议。

    而如果是基于Redis Cluster模式的,我猜测应该不能再前面使用HAProxy的代理去聚合IP。

    关于这种模式的理解,参考:http://www.searu.org/30194.html,说到:当集群处于稳定状态时,所有客户端最终都会保存有一个哈希槽至节点的映射记录,使得集群非常高效: 客户端可以直接向正确的节点发送命令请求, 无须转向、代理或者其他任何可能发生单点故障(single point failure)的实体(entiy)。

    这种应该就是不用代理软件去实现的原因。

    下面是基于Spring+Jedis的配置:

    在Spring配置文件中添加Jedis配置。(三主三从,9001-9003是主,9004-9006是从)

        <!-- 配置redis客户端集群版 -->
        <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
            <constructor-arg>
                <set>
                    <bean class="redis.clients.jedis.HostAndPort">
                        <constructor-arg name="host" value="192.168.XX.XX"/>
                        <constructor-arg name="port" value="9001"/> 
                    </bean>                                         
                    <bean class="redis.clients.jedis.HostAndPort">  
                        <constructor-arg name="host" value="XXXXXXX"/>
                        <constructor-arg name="port" value="9002"/> 
                    </bean>                                         
                    <bean class="redis.clients.jedis.HostAndPort">  
                        <constructor-arg name="host" value="XXXXXXX"/>
                        <constructor-arg name="port" value="9003"/> 
                    </bean>                                         
                    <bean class="redis.clients.jedis.HostAndPort">  
                        <constructor-arg name="host" value="XXXXXXX"/>
                        <constructor-arg name="port" value="9004"/> 
                    </bean>                                         
                    <bean class="redis.clients.jedis.HostAndPort">  
                        <constructor-arg name="host" value="XXXXXXX"/>
                        <constructor-arg name="port" value="9005"/> 
                    </bean>                                         
                    <bean class="redis.clients.jedis.HostAndPort">  
                        <constructor-arg name="host" value="XXXXXXX"/>
                        <constructor-arg name="port" value="9006"/>
                    </bean>
                </set>
            </constructor-arg>
        </bean>
    
    <bean id="jedisClientCluster" class="com.dianshang.rest.component.impl.JedisClientCluster"/>

    封装Redis的一些常用操作(存储String 类型,获取String类型,设置过期时间,删除hash数据等等)

    /**  
     * redis操作工具类  
     * @author xiao  
     *  
     */  
    public class JedisClientCluster implements JedisClient{  
          
        //注入jedisCluster  
        @Autowired  
        private JedisCluster jedisCluster;  
      
        /**  
         * 设置String数据类型  
         *   
         * @param key  
         * @param value  
         * @return  
         */  
        @Override  
        public String set(String key, String value) {  
            return jedisCluster.set(key, value);  
        }  
      
        /**  
         * 获取String数据类型  
         *   
         * @param key  
         * @return  
         */  
        @Override  
        public String get(String key) {  
            return jedisCluster.get(key);  
        }  
          
        /**  
         * 设置hash数据类型  
         *   
         * @param key  
         * @param item  
         * @param value  
         * @return  
         */  
        @Override  
        public Long hset(String key, String item, String value) {  
            return jedisCluster.hset(key, item, value);  
        }  
          
        /**  
         * 获取hash数据类型  
         *   
         * @param key  
         * @param item  
         * @return  
         */  
        @Override  
        public String hget(String key, String item) {  
            return jedisCluster.hget(key, item);  
        }  
          
        /**  
         * 删除hash数据  
         * @param key  
         * @param item  
         * @return  
         */  
        @Override  
        public Long incr(String key) {  
            return jedisCluster.incr(key);  
        }  
          
        /**  
         * 加一操作  
         *   
         * @param key  
         * @return  
         */  
        @Override  
        public Long decr(String key) {  
            return jedisCluster.decr(key);  
        }  
          
        /**  
         * 减一操作  
         *   
         * @param key  
         * @return  
         */  
        @Override  
        public Long expire(String key, int second) {  
            return jedisCluster.expire(key, second);  
        }  
          
        /**  
         * 设置key的过期时间  
         *   
         * @param key  
         * @param second  
         * @return  
         */  
        @Override  
        public Long ttl(String key) {  
            return jedisCluster.ttl(key);  
        }  
          
        /**  
         * 判断key是否过期  
         *   
         * @param key  
         * @return  
         */  
        @Override  
        public Long hdel(String key, String item) {  
             return jedisCluster.hdel(key, item);  
        }  
      
    }  

    测试:

    @Test  
    public void testJedisClientSpring() throws Exception {  
        //创建一个spring容器  
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml");  
        //从容器中获得JedisClient对象  
        JedisClient jedisClient = applicationContext.getBean(JedisClient.class);  
        //jedisClient操作redis  
        jedisClient.set("cliet1", "1000");  
        String string = jedisClient.get("cliet1");  
        System.out.println(string);  
    }  

    参考:

    http://blog.csdn.net/u010539352/article/details/51778242(以上内容部分转自此篇文章)

    http://blog.csdn.net/younger_z/article/details/51366791

    http://m635674608.iteye.com/blog/2292236

    https://www.2cto.com/kf/201609/551965.html

    http://www.sojson.com/blog/203.html

  • 相关阅读:
    数据库的优化
    Java 10
    sleep()和yield()的区别
    mvc框架实现的流程,值得收藏
    MyEclipse项目出现红色!的原因
    The requested resource is not available的解决方案-转载博文
    web.xml详解(web-app_2_3.dtd)规范顺序
    EditText小写字母自动转换成大写(注:设置之后只能显示大写字母)
    Android GridView属性意义集合(转)
    Theme.AppCompat.Light无法找到问题(转)
  • 原文地址:https://www.cnblogs.com/EasonJim/p/7630049.html
Copyright © 2011-2022 走看看