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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM