Redis Cluster集羣主從方案

本文介紹一種經過Jedis和Cluster實現Redis集羣(主從)的高可用方案,該方案須要使用Jedis2.8.0(推薦),Redis3.0及以上版本(強制).html

附:
Redis Cluster集羣主從方案:http://www.cnblogs.com/soul-wonder/p/8891256.html
Redis Sentinel主從高可用方案:http://www.cnblogs.com/soul-wonder/p/8891217.html
node

1、Redis集羣介紹

  • Redis 集羣是一個提供在多個Redis間節點間共享數據的程序集。
  • Redis集羣並不支持處理多個keys的命令,由於這須要在不一樣的節點間移動數據,從而達不到像Redis那樣的性能,在高負載的狀況下可能會致使不可預料的錯誤.
  • Redis 集羣經過分區來提供必定程度的可用性,在實際環境中當某個節點宕機或者不可達的狀況下繼續處理命令.
  • Redis 集羣有16384個哈希槽,每一個key經過CRC16校驗後對16384取模來決定放置哪一個槽.集羣的每一個節點負責一部分hash槽,舉個例子,好比當前集羣有3個節點,那麼: 節點 A 包含 0 到 5500號哈希槽. 節點 B 包含5501 到 11000 號哈希槽. 節點 C 包含11001 到 16384號哈希槽.

2、Redis Cluster集羣的優點:

  • 自動分割數據到不一樣的節點上。
  • 整個集羣的部分節點失敗或者不可達的狀況下可以繼續處理命令。
  • 客戶端與redis節點直連,不須要中間proxy層.客戶端不須要鏈接集羣全部節點,鏈接集羣中任何一個可用節點便可。
  • 支持主從複製模型。(slave->master 選舉,集羣容錯)

3、Redis Cluster集羣的主從複製模型:

爲了使在部分節點失敗或者大部分節點沒法通訊的狀況下集羣仍然可用,因此集羣使用了主從複製模型,假若有A,B,C三個節點的集羣,在沒有複製模型的狀況下,若是節點B失敗了,那麼整個集羣就會覺得缺乏5501-11000這個範圍的槽而不可用.
然而若是在集羣建立的時候咱們爲每一個節點添加一個從節點A1,B1,C1,那麼整個集羣便有三個master節點和三個slave節點組成,這樣在節點B失敗後,集羣便會選舉B1爲新的主節點繼續服務,整個集羣便不會由於槽找不到而不可用了。redis

4、Redis Cluster模型圖

5、Redis的安裝以及cluster配置

下載redis最新的安裝包
wget http://download.redis.io/releases/redis-3.0.7.tar.gz
解壓
tar xzf redis-3.0.7.tar.gz 
安裝支持包tcl
yum install tcl 編譯原文件
make
建立集羣相關文件(方便管理)
mkdir cluster 
cd cluster
mkdir 6379 6380 6381 6382 6383 6384 
cluster下面每一個目錄中都建立一個redis.conf文件. 注意修改文件中的端口號:spring

port 6379
cluster-enabled yes
cluster-config-file nodes_6379.conf
cluster-node-timeout 5000
appendonly yes

把redis-server的可執行文件複製到cluster下面的各個目錄, 而後打開6個shell終端,進入各個目錄,啓動每一個實例, 命令以下: 
./redis-server redis.confshell

檢查6個服務是否都啓動了
apache

搭建集羣
./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384ruby

–replicas 1 表示咱們但願爲集羣中的每一個主節點建立一個從節點。
此時報錯,發現缺乏相應的ruby環境,以下安裝相應環境:
yum install ruby
yum install rubygems
gem install redisapp

安裝好環境後再次搭建集羣
./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 性能

檢測集羣節點相關信息 
./redis-trib.rb check 127.0.0.1:6379 spa

 

能夠發現系統將前3個服務作了主節點,後3個服務做爲了從節點,而且是相對應的。

進入某個節點驗證
./redis-cli -c -h 127.0.0.1 -p 6379

 

能夠發現程序根據key對16384取模的值爲3488,根據hash槽的分佈跳轉到了對應的節點上。 可見集羣環境正常運行

6、Jedis Cluster教程

Xml代碼 :
複製代碼
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- Jedis連接池配置,注意:Jedis版本建議升級到最新 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="100" />
        <property name="maxIdle" value="20" />
        <property name="minIdle" value="10" />
        <property name="blockWhenExhausted" value="true"></property>
        <property name="maxWaitMillis" value="3000" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="testWhileIdle" value="true" />
        <property name="minEvictableIdleTimeMillis" value="60000" />
        <property name="timeBetweenEvictionRunsMillis" value="30000" />
        <property name="numTestsPerEvictionRun" value="-1" />
    </bean>

    <!-- JedisCluster -->
    <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
        <constructor-arg index="0">
            <set>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg index="0" value="192.168.1.111" />
                    <constructor-arg index="1" value="7111" type="int" />
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg index="0" value="192.168.1.112" />
                    <constructor-arg index="1" value="7112" type="int" />
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg index="0" value="192.168.1.113" />
                    <constructor-arg index="1" value="7113" type="int" />
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg index="0" value="192.168.1.114" />
                    <constructor-arg index="1" value="7114" type="int" />
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg index="0" value="192.168.1.115" />
                    <constructor-arg index="1" value="7115" type="int" />
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg index="0" value="192.168.1.116" />
                    <constructor-arg index="1" value="7116" type="int" />
                </bean>
            </set>
        </constructor-arg>
        <constructor-arg index="1" value="2000" type="int"></constructor-arg>
        <constructor-arg index="2" value="100" type="int"></constructor-arg>
        <constructor-arg index="3" ref="jedisPoolConfig"></constructor-arg>
    </bean>

</beans>
複製代碼
 
Java代碼 : 
複製代碼
package wusc.edu.demo.redis;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import redis.clients.jedis.JedisCluster;


public class RedisClusterSpringTest {
    private static final Log log = LogFactory.getLog(RedisClusterSpringTest.class);

    public static void main(String[] args) {
        try {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-context.xml");
            context.start();
            
            JedisCluster jedisCluster = (JedisCluster) context.getBean("jedisCluster");
            int num = 1000;
            String key = "yingjun";
            String value = "";
            for (int i=1; i <= num; i++){
                // 存數據
                //jedisCluster.set(key+i, "yingjun"+i);
                //jedisCluster.setex(key+i, 60, "yingjun"+i);
                
                // 取數據
                value = jedisCluster.get(key+i); 
                log.info(key+i + "=" + value);
                
                // 刪除數據
                //jedisCluster.del(key+i); 
                //value = jedisCluster.get(key+i); 
                //log.info(key+i + "=" + value);
            }

            context.stop();
        } catch (Exception e) {
            log.error("==>RedisSpringTest context start error:", e);
            System.exit(0);
        } finally {
            log.info("===>System.exit");
            System.exit(0);
        }
    }
}
複製代碼
相關文章
相關標籤/搜索