Redis Sentinel的Redis集羣(主從&Sharding)高可用方案

在不使用redis3.0以後版本的狀況下,對於redis服務端通常是採用Sentinel哨兵模式,也就是一主多備的方式。java

這裏,先拋出三個問題,git

問題1:單節點宕機數據丟失?
問題2:多節點(節點間沒有主從關係)數據分片,採用sharedJedisPool,某節點宕機,致使獲取不到鏈接
問題3:主從模式下,經過哨兵配置,單個集羣數據沒法分片(備複製->主的數據,備無寫權限)github

 

關於問題1,解決方式,多臺redis節點,採用Sentinel哨兵模式,也就是一主多備的方式。redis

關於問題2,這裏先不談解決方式,在節點間無依賴的狀況下,採用redis分片存儲數據,也就是採用redis的sharedjedispool鏈接池,他有一個缺點,那就是當個人某個spring

節點宕機後,會致使整個鏈接出問題。api

關於問題3,在一個集羣環境下,從複製主的數據,這個時候一個集羣下的redis實例之間的數據是同步,也就沒有辦法去作數據分片測試

在不適用redis3.0後的新特徵load balance,也就是 ....spa

Redis Cluster  是Redis的集羣實現,內置數據自動分片機制,集羣內部將全部的key映射到16384個Slot中,集羣中的每一個Redis Instance負責其中的一部分的Slot的讀寫。集羣客戶端鏈接集羣中任一Redis Instance便可發送命令,當Redis Instance收到本身不負責的Slot的請求時,會將負責請求Key所在Slot的Redis Instance地址返回給客戶端,客戶端收到後自動將原請求從新發往這個地址,對外部透明。一個Key到底屬於哪一個Slot由crc16(key) % 16384 決定code

關於上面三個問題,在使用redis2.X版本的狀況下,解決方式就是:xml

多個集羣,而後就是集羣之間數據分片,這樣壓力小不少。

舉個例子:

 

 

 

看到上面的圖應該就懂了。

在這裏還有一個比較坑爹的問題就是,spring封裝的那套spring-data-redis ,相對於jedis真的是不太好用,並且關於哨兵的配置文件,就是下面這段,

    <bean id="sentinelConfiguration"  
        class="org.springframework.data.redis.connection.RedisSentinelConfiguration">  
        <property name="master">  
            <bean class="org.springframework.data.redis.connection.RedisNode">  
                <property name="name" value="mymaster"></property>  
            </bean>  
        </property>  
        <property name="sentinels">  
            <set>  
                <bean class="org.springframework.data.redis.connection.RedisNode">  
                    <constructor-arg name="host"  
                        value="192.168.8.50"></constructor-arg>  
                    <constructor-arg name="port"  
                        value="26379"></constructor-arg>  
                </bean>  
            </set>  
        </property>  
    </bean>  

  我在spring3.x版本下,死活報錯,注入不了sentinels,然而打開源碼去看,確實是有的,換成spring4.X後,就沒有出現問題。

嘆氣!!!

決定棄用spring-data-redis,仍是採用jedis。

可是jedis也有一個問題,在jedis2.5以後增長了redis.clients.jedis.JedisSentinelPool這個哨兵管理鏈接池,他也有一個問題,就是他取得的redis操做實例是jedis,而不是sharedJedis,由於sharedJedis,是從sharedJedisPool裏面取出的,這樣是否是又有一個問題,嗯,支持集羣了,但不支持分片了!!

 

顯然不是咱們想要的,怎麼辦呢,Google了下,在github上找到有人去寫了一個鏈接池,地址在這

https://github.com/warmbreeze/sharded-jedis-sentinel-pool,

代碼拿下來後,看了下,應該是能夠的,加上測試下。

<?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-3.0.xsd">
    <!-- 鏈接池配置 -->
     <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="8" />
        <property name="maxTotal" value="50" />  
        <property name="maxWaitMillis" value="1000" /> 
        <property name="testOnBorrow" value="true" />
        <property name="testOnReturn" value="true" />
     </bean>
    <!-- jedis鏈接池配置 -->
<!--     <bean id="jedisPool" class="redis.clients.jedis.JedisSentinelPool">
        <constructor-arg index="0" value="mymaster" />
        <constructor-arg index="1">
            <set>
                <value>192.168.8.50:26379</value>
            </set>
        </constructor-arg>
        <constructor-arg index="2" ref="jedisPoolConfig" />
    </bean> -->
    <!-- 自定義分片處理哨兵池配置 -->
    <bean id="shardedJedisPool" class="com.yto.demo.java.jedis.spring.sentinel.pool.ShardedJedisSentinelPool">
        <constructor-arg index="0" ref="jedisPoolConfig" />
        <constructor-arg index="1">
            <list>
                <value>mymaster</value> <!-- 集羣1 -->
                <value>mymaster02</value> <!-- 集羣2 -->
                
            </list>
        </constructor-arg>
        <constructor-arg index="2">
            <set>
                <value>192.168.8.50:26379</value>
                <value>192.168.8.50:26479</value>
            </set>
        </constructor-arg>
    </bean>
    <!-- 自定義抽象jedis 信息 -->
    <bean id="redisDataSource"  class="com.yto.demo.java.jedis.spring.api.impl.RedisSharedSentinelDataSourceImpl">
        <property name="shardedJedisPool" ref="shardedJedisPool"></property>
    </bean>
    
    <bean id="redisClientTemplate"  class="com.yto.demo.java.jedis.spring.client.RedisSharedSentinelClientTemplate">
        <property name="redisDataSource" ref="redisDataSource"></property>
    </bean>
    
    
 </beans>  

 

ShardedJedisSentinelPool這個代碼本身去git上面拿下來吧!!至於裏面有沒有bug我還沒仔細去看裏面的代碼,可是確實支持主從+分片了。。
相關文章
相關標籤/搜索