在不使用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我還沒仔細去看裏面的代碼,可是確實支持主從+分片了。。