1. 程式人生 > >SpringBoot整合Redis(單機+叢集) —— 含Spring版附件文件

SpringBoot整合Redis(單機+叢集) —— 含Spring版附件文件

首先推薦一個文件:

介紹了redis單機、叢集的搭建,以及Spring專案中如何使用Jedis、JedisCluster進行redis操作,看不懂本文的看這個文件也行。

----------------------------------------------------------------------------------------------------------------------------

如果使用的是redis2.x,在專案中使用客戶端分片(Shard)機制,已經很久之前的版本,該換新了(此處略過),

本文講解基於redis3.x中的叢集,通過兩部分來闡述spring boot整合redis,在專案中使用jedisCluster機制。

第一部分:spring boot自帶整合的redis,比較簡單,看下來

1>不用多說,pom.xml檔案增加redis與spring boot的依賴

  1. <!-- redis依賴包 -->
  2.         <dependency>
  3.             <groupId>org.springframework.boot</groupId>
  4.             <artifactId>spring-boot-starter-redis</artifactId>
  5.             <version>1.4.7.RELEASE
    </version>
  6.         </dependency>

2>application.properties增加redis節點配置
  1. #redis單伺服器配置  
  2. spring.redis.database=0
  3. spring.redis.host=127.0.0.1  
  4. spring.redis.port=6379
  5. spring.redis.password=  
  6. spring.redis.pool.max-active=8
  7. spring.redis.pool.max-wait=-1  
  8. spring.redis.pool.max-idle=8
  9. spring.redis.pool.min-idle
    =0
  10. spring.redis.timeout=0

3>在需要使用的地方增加RedisTemplate依賴,我只在controller試了下.程式碼如下:
  1. package com.xyy.controller;  
  2. import java.util.HashMap;  
  3. import java.util.Map;  
  4. import org.slf4j.Logger;  
  5. import org.slf4j.LoggerFactory;  
  6. import org.springframework.beans.factory.annotation.Autowired;  
  7. import org.springframework.data.redis.core.RedisTemplate;  
  8. import org.springframework.data.redis.core.ValueOperations;  
  9. import org.springframework.ui.ModelMap;  
  10. import org.springframework.web.bind.annotation.PathVariable;  
  11. import org.springframework.web.bind.annotation.RequestMapping;  
  12. import org.springframework.web.bind.annotation.RestController;  
  13. import org.springframework.web.servlet.ModelAndView;  
  14. import com.danga.MemCached.MemCachedClient;  
  15. import com.xyy.model.Favorite;  
  16. import com.xyy.service.FavoriteService;  
  17. /**  
  18.  * Favorite控制層  
  19.  * @ClassName: FavoriteController   
  20.  * @author wujing  
  21.  * @date 2017-07-13 15:09:50  
  22.  */  
  23. @RestController  
  24. @RequestMapping("/favorite")  
  25. public class FavoriteController{  
  26.     private static final Logger LOGGER = LoggerFactory.getLogger(FavoriteController.class);  
  27.     @Autowired  
  28.     private FavoriteService favoriteService;  
  29.     @Autowired  
  30.     private MemCachedClient  memCachedClient ;  
  31.     @Autowired  
  32.     private RedisTemplate redisTemplate;  
  33.     /**  
  34.      * Favorite編輯  
  35.      * @Title: update  
  36.      * @param favorite 修改物件  
  37.      * @return Object  
  38.      * @author wujing   
  39.      * @date 2017-07-13 15:09:50  
  40.      */  
  41.     //@RequestMapping("/detail2/{id}")  
  42.     public Object detail2(@PathVariable Long id,ModelMap modelMap) {  
  43.         Map<String,Object>resultMap = new HashMap<String,Object>();  
  44.         try {  
  45.             Favorite tempFavorite = favoriteService.selectByPrimaryKey(id);  
  46.             resultMap.put("status", "success");  
  47.             resultMap.put("data", tempFavorite);  
  48.         } catch (Exception e) {  
  49.             resultMap.put("status", "error");  
  50.             resultMap.put("errorMsg", "系統異常");  
  51.             LOGGER.error("Favorite新增異常", e);  
  52.         }  
  53.         return resultMap;  
  54.     }  
  55.     @RequestMapping("/detail/{id}")  
  56.     public Object detail(@PathVariable Long id,ModelMap modelMap) {  
  57.         try {  
  58.             /*Favorite tempFavorite = (Favorite) memCachedClient.get("favorite:"+id);  
  59.             if(tempFavorite == null) {  
  60.                 tempFavorite = favoriteService.selectByPrimaryKey(id);  
  61.                 memCachedClient.set("favorite:"+id, tempFavorite);  
  62.             }*/  
  63.             ValueOperations<String, Favorite>operations = redisTemplate.opsForValue();  
  64.             Favorite tempFavorite = operations.get("favorite:"+id);  
  65.             if(tempFavorite == null) {  
  66.                 tempFavorite = favoriteService.selectByPrimaryKey(id);  
  67.                 operations.set("favorite:"+id, tempFavorite);  
  68.             }  
  69.             modelMap.put("tempFavorite", tempFavorite);  
  70.         } catch (Exception e) {  
  71.             LOGGER.error("Favorite查詢異常", e);  
  72.         }  
  73.         return new ModelAndView("favorite/detail");  
  74.     }  
  75. }  

就是這麼簡單,不得不說spring boot做了很多事,極大的簡化了開發的難度再見..讓我等屌絲完全沉淪於碼農了

隨著專案的擴大,資料的增加,專案面臨的考驗也越來越明顯,效能,擴充套件,容災..等都是很重要的,這時候分散式或叢集就顯得尤為重要了

第二部分:spring boot整合叢集版的redis

redis 3.X,在專案中使用jedisCluster機制。

1>pom.xml增加jedisCluster依賴

  1. </dependency>
  2.                         <groupId>org.springframework.boot</groupId>
  3.             <artifactId>spring-boot-starter-redis</artifactId>
  4.             <version>1.4.7.RELEASE</version>
  5.         </dependency>
2>新增redis叢集節點配置檔案,此處有兩種方法

        1:直接在application.properties新增,此處就不詳細介紹了

        2:採用javaben的方式配置(此處需要注意spring boot 1.5以後的版本@ConfigurationProperties取消了locations屬性),可以通過@PropertySource("classpath:redis.properties")引入配置檔案,當然如果寫在application.properties下,不需要引用該註解,如下

  1. package com.xyy.util.cached.redis;  
  2. import org.springframework.boot.context.properties.ConfigurationProperties;  
  3. import org.springframework.context.annotation.PropertySource;  
  4. import org.springframework.stereotype.Component;  
  5. /**  
  6.  * redis叢集配置檔案  
  7.  * @ClassName: RedisProperties   
  8.  * @author wangqinghua  
  9.  * @date 2017年7月24日 下午5:29:19  
  10.  */  
  11. @Component  
  12. @ConfigurationProperties(prefix = "xyy.redis.pool")  
  13. @PropertySource("classpath:redis.properties")  
  14. public class RedisProperties {  
  15.     /** redis叢集節點 */  
  16.     private String nodes;  
  17.     /** 連線超時時間 */  
  18.     private int timeout;  
  19.     /** 重連次數 */  
  20.     private int maxAttempts;  
  21.     public String getNodes() {  
  22.         return nodes;  
  23.     }  
  24.     public void setNodes(String nodes) {  
  25.         this.nodes = nodes;  
  26.     }  
  27.     public int getTimeout() {  
  28.         return timeout;  
  29.     }  
  30.     public void setTimeout(int timeout) {  
  31.         this.timeout = timeout;  
  32.     }  
  33.     public int getMaxAttempts() {  
  34.         return maxAttempts;  
  35.     }  
  36.     public void setMaxAttempts(int maxAttempts) {  
  37.         this.maxAttempts = maxAttempts;  
  38.     }  
  39. }  

redis.properties配置檔案如下:
  1. #redis叢集配置  
  2. xyy.redis.pool.nodes=127.0.0.1:6379,<spanstyle="line-height: 1.5;"></span>127.0.0.1:6380,127.0.0.1:6381  
  3. xyy.redis.pool.timeout=3000
  4. xyy.redis.pool.maxAttempts=5

3>建立JedisCluster物件
  1. package com.xyy.util.cached.redis;  
  2. import java.util.HashSet;  
  3. import java.util.Set;  
  4. import org.springframework.beans.factory.annotation.Autowired;  
  5. import org.springframework.context.annotation.Bean;  
  6. import org.springframework.context.annotation.Configuration;  
  7. import redis.clients.jedis.HostAndPort;  
  8. import redis.clients.jedis.JedisCluster;  
  9. /**  
  10.  * 生成JedisCluster物件  
  11.  * @ClassName: JedisClusterConfig   
  12.  * @author wangqinghua  
  13.  * @date 2017年7月24日 下午7:08:03  
  14.  */  
  15. @Configuration  
  16. public class JedisClusterConfig {  
  17.     @Autowired  
  18.     private RedisProperties redisProperties;  
  19.     /**  
  20.      * 注意:  
  21.      * 這裡返回的JedisCluster是單例的,並且可以直接注入到其他類中去使用  
  22.      * @return  
  23.      */  
  24.     @Bean  
  25.     public JedisCluster getJedisCluster() {  
  26.         String[] serverArray = redisProperties.getNodes().split(",");//獲取伺服器陣列(這裡要相信自己的輸入,所以沒有考慮空指標問題)  
  27.         Set<HostAndPort>nodes = new HashSet<>();  
  28.         for (String ipPort : serverArray) {  
  29.             String[] ipPortPair = ipPort.split(":");  
  30.             nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));  
  31.         }  
  32.         return new JedisCluster(nodes, redisProperties.getTimeout(),redisProperties.getMaxAttempts());  
  33.     }  
  34. }  

4>自定義RedisTemplate
  1. package com.xyy.util.cached.redis;  
  2. import org.slf4j.Logger;  
  3. import org.slf4j.LoggerFactory;  
  4. import org.springframework.beans.factory.annotation.Autowired;  
  5. import org.springframework.stereotype.Component;  
  6. import redis.clients.jedis.JedisCluster;  
  7. /**  
  8.  * 自定義redisTemplate  
  9.  * @ClassName: XyyRedisTemplate   
  10.  * @author wangqinghua  
  11.  * @date 2017年7月24日 下午7:09:49  
  12.  */  
  13. @Component  
  14. public class XyyRedisTemplate {  
  15.     private static final Logger LOGGER    = LoggerFactory.getLogger(XyyRedisTemplate.class);  
  16.     @Autowired  
  17.     private JedisCluster        jedisCluster;  
  18.     @Autowired  
  19.     private RedisProperties     redisProperties;  
  20.     private static final String KEY_SPLIT = ":"; //用於隔開快取字首與快取鍵值   
  21.     /**  
  22.      * 設定快取   
  23.      * @param prefix 快取字首(用於區分快取,防止快取鍵值重複)  
  24.      * @param key    快取key  
  25.      * @param value  快取value  
  26.      */  
  27.     public void set(String prefix, String key, String value) {  
  28.         jedisCluster.set(prefix + KEY_SPLIT + key, value);  
  29.         LOGGER.debug("RedisUtil:set cache key={},value={}", prefix + KEY_SPLIT + key, value);  
  30.     }  
  31.     /**  
  32.      * 設定快取,並且自己指定過期時間  
  33.      * @param prefix  
  34.      * @param key  
  35.      * @param value  
  36.      * @param expireTime 過期時間  
  37.      */  
  38.     public void setWithExpireTime(String prefix, String key, String value, int expireTime) {  
  39.         jedisCluster.setex(prefix + KEY_SPLIT + key, expireTime, value);  
  40.         LOGGER.debug("RedisUtil:setWithExpireTime cache key={},value={},expireTime={}", prefix + KEY_SPLIT + key, value,  
  41.             expireTime);  
  42.     }  
  43.     /**  
  44.      * 設定快取,並且由配置檔案指定過期時間  
  45.      * @param prefix  
  46.      * @param key  
  47.      * @param value  
  48.      */  
  49.     public void setWithExpireTime(String prefix, String key, String value) {  
  50.         int EXPIRE_SECONDS = redisProperties.getTimeout();  
  51.         jedisCluster.setex(prefix + KEY_SPLIT + key, EXPIRE_SECONDS, value);  
  52.         LOGGER.debug("RedisUtil:setWithExpireTime cache key={},value={},expireTime={}", prefix + KEY_SPLIT + key, value,  
  53.             EXPIRE_SECONDS);  
  54.     }  
  55.     /**  
  56.      * 獲取指定key的快取  
  57.      * @param prefix  
  58.      * @param key  
  59.      */  
  60.     public String get(String prefix, String key) {  
  61.         String value = jedisCluster.get(prefix + KEY_SPLIT + key);  
  62.         LOGGER.debug("RedisUtil:get cache key={},value={}", prefix + KEY_SPLIT + key, value);  
  63.         return value;  
  64.     }  
  65.     /**  
  66.      * 刪除指定key的快取  
  67.      * @param prefix  
  68.      * @param key  
  69.      */  
  70.     public void deleteWithPrefix(String prefix, String key) {  
  71.         jedisCluster.del(prefix + KEY_SPLIT + key);  
  72.         LOGGER.debug("RedisUtil:delete cache key={}", prefix + KEY_SPLIT + key);  
  73.     }  
  74.     public void delete(String key) {  
  75.         jedisCluster.del(key);  
  76.         LOGGER.debug("RedisUtil:delete cache key={}", key);  
  77.     }  
  78. }  

5>如何使用,和spring boot自帶的就很類似了
  1. package com.xyy.controller;  
  2. import java.util.HashMap;  
  3. import java.util.Map;  
  4. import org.slf4j.Logger;  
  5. import org.slf4j.LoggerFactory;  
  6. import org.springframework.beans.factory.annotation.Autowired;  
  7. import org.springframework.data.redis.core.RedisTemplate;  
  8. import org.springframework.ui.ModelMap;  
  9. import org.springframework.util.StringUtils;  
  10. import org.springframework.web.bind.annotation.PathVariable;  
  11. import org.springframework.web.bind.annotation.RequestMapping;  
  12. import org.springframework.web.bind.annotation.RestController;  
  13. import org.springframework.web.servlet.ModelAndView;  
  14. import com.danga.MemCached.MemCachedClient;  
  15. import com.xyy.model.Favorite;  
  16. import com.xyy.service.FavoriteService;  
  17. import com.xyy.util.JsonUtil;  
  18. import com.xyy.util.cached.redis.XyyRedisTemplate;  
  19. /**  
  20.  * Favorite控制層  
  21.  * @ClassName: FavoriteController   
  22.  * @author wujing  
  23.  * @date 2017-07-13 15:09:50  
  24.  */  
  25. @RestController  
  26. @RequestMapping("/favorite")  
  27. public class FavoriteController{  
  28.     private static final Logger LOGGER = LoggerFactory.getLogger(FavoriteController.class);  
  29.     @Autowired  
  30.     private FavoriteService favoriteService;  
  31.     @Autowired  
  32.     private MemCachedClient  memCachedClient ;  
  33.     @Autowired  
  34.     private RedisTemplate redisTemplate;  
  35.     @Autowired  
  36.     private XyyRedisTemplate xyyRedisTemplate;  
  37.     /**  
  38.      * Favorite編輯  
  39.      * @Title: update  
  40.      * @param favorite 修改物件  
  41.      * @return Object  
  42.      * @author wujing   
  43.      * @date 2017-07-13 15:09:50  
  44.      */  
  45.     //@RequestMapping("/detail2/{id}")  
  46.     public Object detail2(@PathVariable Long id,ModelMap modelMap) {  
  47.         Map<String,Object>resultMap = new HashMap<String,Object>();  
  48.         try {  
  49.             Favorite tempFavorite = favoriteService.selectByPrimaryKey(id);  
  50.             resultMap.put("status", "success");  
  51.             resultMap.put("data", tempFavorite);  
  52.         } catch (Exception e) {  
  53.             resultMap.put("status", "error");  
  54.             resultMap.put("errorMsg", "系統異常");  
  55.             LOGGER.error("Favorite新增異常", e);  
  56.         }  
  57.         return resultMap;  
  58.     }  
  59.     @RequestMapping("/detail/{id}")  
  60.     public Object detail(@PathVariable Long id,ModelMap modelMap) {  
  61.         try {  
  62.             /*Favorite tempFavorite = (Favorite) memCachedClient.get("favorite:"+id);  
  63.             if(tempFavorite == null) {  
  64.                 tempFavorite = favoriteService.selectByPrimaryKey(id);  
  65.                 memCachedClient.set("favorite:"+id, tempFavorite);  
  66.             }*/  
  67.             /*ValueOperations<String, Favorite>operations = redisTemplate.opsForValue();  
  68.             Favorite tempFavorite = operations.get("favorite:"+id);  
  69.             if(tempFavorite == null) {  
  70.                 tempFavorite = favoriteService.selectByPrimaryKey(id);  
  71.                 operations.set("favorite:"+id, tempFavorite);  
  72.             }*/  
  73.             Favorite tempFavorite = null;  
  74.             String value = xyyRedisTemplate.get("favorite",String.valueOf(id));  
  75.             if(StringUtils.isEmpty(value)) {  
  76.                 tempFavorite = favoriteService.selectByPrimaryKey(id);  
  77.                 xyyRedisTemplate.set("favorite",String.valueOf(id), JsonUtil.objToString(tempFavorite));  
  78.             }else {  
  79.                 tempFavorite = JsonUtil.stringToObj(value, Favorite.class);  
  80.             }  
  81.             modelMap.put("tempFavorite", tempFavorite);  
  82.         } catch (Exception e) {  
  83.             LOGGER.error("Favorite查詢異常", e);  
  84.         }  
  85.         return new ModelAndView("favorite/detail");  
  86.     }  
  87. }  

JsonUtil工具包,為公司自定義檔案,這個就不公開了,可以自行採用各種json包來解析微笑....

redis整合,在這裡,也將告一段落了,有什麼疑問歡迎留言!再見