架構細節:java
(1)全部的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬node
(2)節點的fail是經過投票機制即集羣中超過半數的節點檢測失效時才生效redis
(3)客戶端與redis節點直連,不須要中間proxy層.客戶端不須要鏈接集羣全部節點,鏈接集羣中任何一個可用節點便可算法
(4)redis-cluster把全部的物理節點映射到[0-16383]slot上,cluster 負責維護node<->slot<->valuespring
Redis 集羣中內置了 16384 個哈希槽,當須要在 Redis 集羣中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結果,而後把結果對 16384 求餘數,這樣每一個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大體均等的將哈希槽映射到不一樣的節點數據庫
搭建資料編程
tar zxvf redis-3.2.5.tar.gz
sudo mv -r redis-3.2.3/* /usr/local/redis/ 進入redis目錄 cd /usr/local/redis/
sudo make
sudo make test 這段運行時間會較長,能夠略過
sudo make install
sudo make install PREFIX=/usr/local/redis-clusterjson
和緩存
cd redis01
./redis-server redis.conf
cd ..ruby
sudo apt-get install ruby
sudo gem install redis-3.0.0.gem
./redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
真正創建redis集羣時,更改成運行redis主機們的ip地址(要關閉防火牆)
redis-cli -p 7002 -c # -c表示操做的是集羣
<!-- Redis客戶端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
1)直接操做版
@Test public void JedisClient(){ // 1.建立一個Jedis對象。須要指定服務端的ip及端口 Jedis jedis = new Jedis("127.0.0.1", 6379); // 2.使用Jedis對象操做數據庫 jedis.set("k1","v1"); String k1 = jedis.get("k1"); System.out.println(k1); // 3.關閉Jedis對象 jedis.close(); }
2)鏈接池版
@Test public void JedisPool(){ // 1.建立一個JedisPool對象。須要指定服務端的ip及端口 JedisPool jedisPool = new JedisPool("127.0.0.1", 6379); // 2.從JedisPool中得到Jedis對象 Jedis jedis = jedisPool.getResource(); // 3.使用Jedis操做redis服務器 jedis.set("k2","v2"); String k1 = jedis.get("k2"); System.out.println(k1); // 4.操做完畢後關閉jedis對象,鏈接池回收資源 jedis.close(); // 5.關閉JedisPool對象 jedisPool.close(); }
3)鏈接集羣版
@Test // 集羣默認使用的就是鏈接池,因此不用咱們來配了 public void JedisCluster(){ // 1.使用JedisCluster對象。須要一個Set<HostAndPort>參數。Redis節點的列表。 Set<HostAndPort> nodes = new HashSet<>(); nodes.add(new HostAndPort("127.0.0.1", 7001)); nodes.add(new HostAndPort("127.0.0.1", 7002)); nodes.add(new HostAndPort("127.0.0.1", 7003)); nodes.add(new HostAndPort("127.0.0.1", 7004)); nodes.add(new HostAndPort("127.0.0.1", 7005)); nodes.add(new HostAndPort("127.0.0.1", 7006)); // 2.直接使用JedisCluster對象操做redis。在系統中單例存在。 JedisCluster jedisCluster = new JedisCluster(nodes); jedisCluster.set("k3", "v3"); String result = jedisCluster.get("k3"); System.out.println(result); // 3.系統關閉前,關閉JedisCluster對象。 jedisCluster.close(); }
緩存數據庫查詢數據,當進行增刪改方法時,刪除緩存;因爲咱們平時用單機版的就好了,項目發佈時在使用集羣版,因此咱們能夠採用面向接口編程;緩存是在service中配置的
1 public interface JedisClient { 2 3 String set(String key, String value); 4 String get(String key); 5 Boolean exists(String key); 6 Long expire(String key, int seconds); 7 Long ttl(String key); 8 Long incr(String key); 9 Long hset(String key, String field, String value); 10 String hget(String key, String field); 11 Long hdel(String key, String... field); 12 Boolean hexists(String key, String field); 13 List<String> hvals(String key); 14 Long del(String key); 15 }
1 package cn.e3mall.common.jedis; 2 3 import java.util.List; 4 5 import redis.clients.jedis.Jedis; 6 import redis.clients.jedis.JedisPool; 7 8 public class JedisClientPool implements JedisClient { 9 10 private JedisPool jedisPool; 11 12 public JedisPool getJedisPool() { 13 return jedisPool; 14 } 15 16 public void setJedisPool(JedisPool jedisPool) { 17 this.jedisPool = jedisPool; 18 } 19 20 @Override 21 public String set(String key, String value) { 22 Jedis jedis = jedisPool.getResource(); 23 String result = jedis.set(key, value); 24 jedis.close(); 25 return result; 26 } 27 28 @Override 29 public String get(String key) { 30 Jedis jedis = jedisPool.getResource(); 31 String result = jedis.get(key); 32 jedis.close(); 33 return result; 34 } 35 36 @Override 37 public Boolean exists(String key) { 38 Jedis jedis = jedisPool.getResource(); 39 Boolean result = jedis.exists(key); 40 jedis.close(); 41 return result; 42 } 43 44 @Override 45 public Long expire(String key, int seconds) { 46 Jedis jedis = jedisPool.getResource(); 47 Long result = jedis.expire(key, seconds); 48 jedis.close(); 49 return result; 50 } 51 52 @Override 53 public Long ttl(String key) { 54 Jedis jedis = jedisPool.getResource(); 55 Long result = jedis.ttl(key); 56 jedis.close(); 57 return result; 58 } 59 60 @Override 61 public Long incr(String key) { 62 Jedis jedis = jedisPool.getResource(); 63 Long result = jedis.incr(key); 64 jedis.close(); 65 return result; 66 } 67 68 @Override 69 public Long hset(String key, String field, String value) { 70 Jedis jedis = jedisPool.getResource(); 71 Long result = jedis.hset(key, field, value); 72 jedis.close(); 73 return result; 74 } 75 76 @Override 77 public String hget(String key, String field) { 78 Jedis jedis = jedisPool.getResource(); 79 String result = jedis.hget(key, field); 80 jedis.close(); 81 return result; 82 } 83 84 @Override 85 public Long hdel(String key, String... field) { 86 Jedis jedis = jedisPool.getResource(); 87 Long result = jedis.hdel(key, field); 88 jedis.close(); 89 return result; 90 } 91 92 @Override 93 public Boolean hexists(String key, String field) { 94 Jedis jedis = jedisPool.getResource(); 95 Boolean result = jedis.hexists(key, field); 96 jedis.close(); 97 return result; 98 } 99 100 @Override 101 public List<String> hvals(String key) { 102 Jedis jedis = jedisPool.getResource(); 103 List<String> result = jedis.hvals(key); 104 jedis.close(); 105 return result; 106 } 107 108 @Override 109 public Long del(String key) { 110 Jedis jedis = jedisPool.getResource(); 111 Long result = jedis.del(key); 112 jedis.close(); 113 return result; 114 } 115 116 }
1 package cn.e3mall.common.jedis; 2 3 import java.util.List; 4 5 import redis.clients.jedis.JedisCluster; 6 7 public class JedisClientCluster implements JedisClient { 8 9 private JedisCluster jedisCluster; 10 11 12 public JedisCluster getJedisCluster() { 13 return jedisCluster; 14 } 15 16 public void setJedisCluster(JedisCluster jedisCluster) { 17 this.jedisCluster = jedisCluster; 18 } 19 20 @Override 21 public String set(String key, String value) { 22 return jedisCluster.set(key, value); 23 } 24 25 @Override 26 public String get(String key) { 27 return jedisCluster.get(key); 28 } 29 30 @Override 31 public Boolean exists(String key) { 32 return jedisCluster.exists(key); 33 } 34 35 @Override 36 public Long expire(String key, int seconds) { 37 return jedisCluster.expire(key, seconds); 38 } 39 40 @Override 41 public Long ttl(String key) { 42 return jedisCluster.ttl(key); 43 } 44 45 @Override 46 public Long incr(String key) { 47 return jedisCluster.incr(key); 48 } 49 50 @Override 51 public Long hset(String key, String field, String value) { 52 return jedisCluster.hset(key, field, value); 53 } 54 55 @Override 56 public String hget(String key, String field) { 57 return jedisCluster.hget(key, field); 58 } 59 60 @Override 61 public Long hdel(String key, String... field) { 62 return jedisCluster.hdel(key, field); 63 } 64 65 @Override 66 public Boolean hexists(String key, String field) { 67 return jedisCluster.hexists(key, field); 68 } 69 70 @Override 71 public List<String> hvals(String key) { 72 return jedisCluster.hvals(key); 73 } 74 75 @Override 76 public Long del(String key) { 77 return jedisCluster.del(key); 78 } 79 80 }
application-redis.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> <!-- 鏈接redis單機版 --> <bean id="jedisClientPool" class="cn.e3mall.common.jedis.JedisClientPool"> <property name="jedisPool" ref="jedisPool"></property> </bean> <bean id="jedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg name="host" value="127.0.0.1"/> <constructor-arg name="port" value="6379"/> </bean> <!-- 鏈接redis集羣 --> <bean id="jedisClientCluster" class="cn.e3mall.common.jedis.JedisClientCluster"> <property name="jedisCluster" ref="jedisCluster"/> </bean> <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster"> <constructor-arg name="nodes"> <set> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="127.0.0.1"/> <constructor-arg name="port" value="7001"/> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="127.0.0.1"/> <constructor-arg name="port" value="7002"/> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="127.0.0.1"/> <constructor-arg name="port" value="7003"/> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="127.0.0.1"/> <constructor-arg name="port" value="7004"/> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="127.0.0.1"/> <constructor-arg name="port" value="7005"/> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="127.0.0.1"/> <constructor-arg name="port" value="7006"/> </bean> </set> </constructor-arg> </bean> </beans>
新增緩存後
@Service @Transactional public class ContentServiceImpl implements ContentService { @Autowired private TbContentMapper contentMapper; @Autowired private JedisClient jedisClient; @Value("${CONTENT_LIST}") private String CONTENT_LIST; /** * 保存(大廣告..)內容 * @param content * @return */ @Override public E3Result save(TbContent content) { // 1.封裝參數 content.setCreated(new Date()); content.setCreated(new Date()); // 2.插入 contentMapper.insert(content); try { jedisClient.hdel(CONTENT_LIST,content.getCategoryId().toString()); } catch (Exception ex) { ex.printStackTrace(); } // 3.返回 return E3Result.ok(); } /** * 根據分類id,取出各個分類的數據 * @param i * @return */ @Override public List<TbContent> findByCategoryId(Long i) { try{ // 1)先從redis緩存中獲取,須要的是字符串格式 String json = jedisClient.hget(CONTENT_LIST, i + ""); // 2)轉成list if(StringUtils.isNotBlank(json)){ List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class); return list; } } catch (Exception ex){ ex.printStackTrace(); } // 1.設置查詢條件 TbContentExample example = new TbContentExample(); TbContentExample.Criteria criteria = example.createCriteria(); criteria.andCategoryIdEqualTo(i); // 2.執行查詢並返回 List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example); try { // 1)將list轉成字符串 String json = JsonUtils.objectToJson(list); // 2)設置到redis中 jedisClient.hset(CONTENT_LIST,i+"",json); }catch (Exception ex){ ex.printStackTrace(); } return list; } }