在不使用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版本的情況下,解決方式就是:
多個集群,然后就是集群之間數據分片,這樣壓力小很多。
舉個例子:


看到上面的圖應該就懂了。
在這里還有一個比較坑爹的問題就是,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我還沒仔細去看里面的代碼,但是確實支持主從+分片了。。
