天天看點

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

标題中的Sentinel:就連接配接池帶哨兵模式,而不是CRUD帶哨兵模式

在不使用redis3.0之後版本的情況下,對于redis服務端一般是采用Sentinel哨兵模式,也就是一主多備的方式。

這裡,先抛出三個問題,

問題1:單節點當機資料丢失?

問題2:多節點(節點間沒有主從關系)資料分片,采用sharedJedisPool,某節點當機,導緻擷取不到連接配接

問題3:主從模式下,通過哨兵配置,單個叢集資料無法分片(備複制->主的資料,備無寫權限)

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

關于問題2,這裡先不談解決方式,在節點間無依賴的情況下,采用redis分片存儲資料,也就是采用redis的sharedjedispool連接配接池,他有一個缺點,那就是當我的某個

節點當機後,會導緻整個連接配接出問題。

關于問題3,在一個叢集環境下,從複制主的資料,這個時候一個叢集下的redis執行個體之間的資料是同步,也就沒有辦法去做資料分片

在不适用redis3.0後的新特征load balance,也就是 ....

Redis Cluster  是Redis的叢集實作,内置資料自動分片機制,叢集内部将所有的key映射到16384個Slot中,叢集中的每個Redis Instance負責其中的一部分的Slot的讀寫。叢集用戶端連接配接叢集中任一Redis Instance即可發送指令,當Redis Instance收到自己不負責的Slot的請求時,會将負責請求Key所在Slot的Redis Instance位址傳回給用戶端,用戶端收到後自動将原請求重新發往這個位址,對外部透明。一個Key到底屬于哪個Slot由crc16(key) % 16384 決定

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

多個叢集,然後就是叢集之間資料分片,這樣壓力小很多。

舉個例子:

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

​<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裡面取出的,這樣是不是又有一個問題,嗯,支援叢集了,但不支援分片了!!

Redis Sentinel的Redis叢集(主從&amp;Sharding)高可用方案

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

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

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

Redis Sentinel的Redis叢集(主從&amp;Sharding)高可用方案
<?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>      
Redis Sentinel的Redis叢集(主從&amp;Sharding)高可用方案
ShardedJedisSentinelPool這個代碼自己去git上面拿下來吧!!至于裡面有沒有bug我還沒仔細去看裡面的代碼,但是确實支援主從+分片了。。