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的依賴
- <!-- redis依賴包 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-redis</artifactId>
- <version>1.4.7.RELEASE
- </dependency>
2>application.properties增加redis節點配置
- #redis單伺服器配置
- spring.redis.database=0
- spring.redis.host=127.0.0.1
- spring.redis.port=6379
- spring.redis.password=
- spring.redis.pool.max-active=8
- spring.redis.pool.max-wait=-1
- spring.redis.pool.max-idle=8
- spring.redis.pool.min-idle
- spring.redis.timeout=0
3>在需要使用的地方增加RedisTemplate依賴,我只在controller試了下.程式碼如下:
- package com.xyy.controller;
- import java.util.HashMap;
- import java.util.Map;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.data.redis.core.ValueOperations;
- import org.springframework.ui.ModelMap;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import org.springframework.web.servlet.ModelAndView;
- import com.danga.MemCached.MemCachedClient;
- import com.xyy.model.Favorite;
- import com.xyy.service.FavoriteService;
- /**
- * Favorite控制層
- * @ClassName: FavoriteController
- * @author wujing
- * @date 2017-07-13 15:09:50
- */
- @RestController
- @RequestMapping("/favorite")
- public class FavoriteController{
- private static final Logger LOGGER = LoggerFactory.getLogger(FavoriteController.class);
- @Autowired
- private FavoriteService favoriteService;
- @Autowired
- private MemCachedClient memCachedClient ;
- @Autowired
- private RedisTemplate redisTemplate;
- /**
- * Favorite編輯
- * @Title: update
- * @param favorite 修改物件
- * @return Object
- * @author wujing
- * @date 2017-07-13 15:09:50
- */
- //@RequestMapping("/detail2/{id}")
- public Object detail2(@PathVariable Long id,ModelMap modelMap) {
- Map<String,Object>resultMap = new HashMap<String,Object>();
- try {
- Favorite tempFavorite = favoriteService.selectByPrimaryKey(id);
- resultMap.put("status", "success");
- resultMap.put("data", tempFavorite);
- } catch (Exception e) {
- resultMap.put("status", "error");
- resultMap.put("errorMsg", "系統異常");
- LOGGER.error("Favorite新增異常", e);
- }
- return resultMap;
- }
- @RequestMapping("/detail/{id}")
- public Object detail(@PathVariable Long id,ModelMap modelMap) {
- try {
- /*Favorite tempFavorite = (Favorite) memCachedClient.get("favorite:"+id);
- if(tempFavorite == null) {
- tempFavorite = favoriteService.selectByPrimaryKey(id);
- memCachedClient.set("favorite:"+id, tempFavorite);
- }*/
- ValueOperations<String, Favorite>operations = redisTemplate.opsForValue();
- Favorite tempFavorite = operations.get("favorite:"+id);
- if(tempFavorite == null) {
- tempFavorite = favoriteService.selectByPrimaryKey(id);
- operations.set("favorite:"+id, tempFavorite);
- }
- modelMap.put("tempFavorite", tempFavorite);
- } catch (Exception e) {
- LOGGER.error("Favorite查詢異常", e);
- }
- return new ModelAndView("favorite/detail");
- }
- }
就是這麼簡單,不得不說spring boot做了很多事,極大的簡化了開發的難度..讓我等屌絲完全沉淪於碼農了
隨著專案的擴大,資料的增加,專案面臨的考驗也越來越明顯,效能,擴充套件,容災..等都是很重要的,這時候分散式或叢集就顯得尤為重要了
redis 3.X,在專案中使用jedisCluster機制。
1>pom.xml增加jedisCluster依賴
- </dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-redis</artifactId>
- <version>1.4.7.RELEASE</version>
- </dependency>
1:直接在application.properties新增,此處就不詳細介紹了
2:採用javaben的方式配置(此處需要注意spring boot 1.5以後的版本@ConfigurationProperties取消了locations屬性),可以通過@PropertySource("classpath:redis.properties")引入配置檔案,當然如果寫在application.properties下,不需要引用該註解,如下
- package com.xyy.util.cached.redis;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.context.annotation.PropertySource;
- import org.springframework.stereotype.Component;
- /**
- * redis叢集配置檔案
- * @ClassName: RedisProperties
- * @author wangqinghua
- * @date 2017年7月24日 下午5:29:19
- */
- @Component
- @ConfigurationProperties(prefix = "xyy.redis.pool")
- @PropertySource("classpath:redis.properties")
- public class RedisProperties {
- /** redis叢集節點 */
- private String nodes;
- /** 連線超時時間 */
- private int timeout;
- /** 重連次數 */
- private int maxAttempts;
- public String getNodes() {
- return nodes;
- }
- public void setNodes(String nodes) {
- this.nodes = nodes;
- }
- public int getTimeout() {
- return timeout;
- }
- public void setTimeout(int timeout) {
- this.timeout = timeout;
- }
- public int getMaxAttempts() {
- return maxAttempts;
- }
- public void setMaxAttempts(int maxAttempts) {
- this.maxAttempts = maxAttempts;
- }
- }
redis.properties配置檔案如下:
- #redis叢集配置
- 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
- xyy.redis.pool.timeout=3000
- xyy.redis.pool.maxAttempts=5
3>建立JedisCluster物件
- package com.xyy.util.cached.redis;
- import java.util.HashSet;
- import java.util.Set;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import redis.clients.jedis.HostAndPort;
- import redis.clients.jedis.JedisCluster;
- /**
- * 生成JedisCluster物件
- * @ClassName: JedisClusterConfig
- * @author wangqinghua
- * @date 2017年7月24日 下午7:08:03
- */
- @Configuration
- public class JedisClusterConfig {
- @Autowired
- private RedisProperties redisProperties;
- /**
- * 注意:
- * 這裡返回的JedisCluster是單例的,並且可以直接注入到其他類中去使用
- * @return
- */
- @Bean
- public JedisCluster getJedisCluster() {
- String[] serverArray = redisProperties.getNodes().split(",");//獲取伺服器陣列(這裡要相信自己的輸入,所以沒有考慮空指標問題)
- Set<HostAndPort>nodes = new HashSet<>();
- for (String ipPort : serverArray) {
- String[] ipPortPair = ipPort.split(":");
- nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));
- }
- return new JedisCluster(nodes, redisProperties.getTimeout(),redisProperties.getMaxAttempts());
- }
- }
4>自定義RedisTemplate
- package com.xyy.util.cached.redis;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import redis.clients.jedis.JedisCluster;
- /**
- * 自定義redisTemplate
- * @ClassName: XyyRedisTemplate
- * @author wangqinghua
- * @date 2017年7月24日 下午7:09:49
- */
- @Component
- public class XyyRedisTemplate {
- private static final Logger LOGGER = LoggerFactory.getLogger(XyyRedisTemplate.class);
- @Autowired
- private JedisCluster jedisCluster;
- @Autowired
- private RedisProperties redisProperties;
- private static final String KEY_SPLIT = ":"; //用於隔開快取字首與快取鍵值
- /**
- * 設定快取
- * @param prefix 快取字首(用於區分快取,防止快取鍵值重複)
- * @param key 快取key
- * @param value 快取value
- */
- public void set(String prefix, String key, String value) {
- jedisCluster.set(prefix + KEY_SPLIT + key, value);
- LOGGER.debug("RedisUtil:set cache key={},value={}", prefix + KEY_SPLIT + key, value);
- }
- /**
- * 設定快取,並且自己指定過期時間
- * @param prefix
- * @param key
- * @param value
- * @param expireTime 過期時間
- */
- public void setWithExpireTime(String prefix, String key, String value, int expireTime) {
- jedisCluster.setex(prefix + KEY_SPLIT + key, expireTime, value);
- LOGGER.debug("RedisUtil:setWithExpireTime cache key={},value={},expireTime={}", prefix + KEY_SPLIT + key, value,
- expireTime);
- }
- /**
- * 設定快取,並且由配置檔案指定過期時間
- * @param prefix
- * @param key
- * @param value
- */
- public void setWithExpireTime(String prefix, String key, String value) {
- int EXPIRE_SECONDS = redisProperties.getTimeout();
- jedisCluster.setex(prefix + KEY_SPLIT + key, EXPIRE_SECONDS, value);
- LOGGER.debug("RedisUtil:setWithExpireTime cache key={},value={},expireTime={}", prefix + KEY_SPLIT + key, value,
- EXPIRE_SECONDS);
- }
- /**
- * 獲取指定key的快取
- * @param prefix
- * @param key
- */
- public String get(String prefix, String key) {
- String value = jedisCluster.get(prefix + KEY_SPLIT + key);
- LOGGER.debug("RedisUtil:get cache key={},value={}", prefix + KEY_SPLIT + key, value);
- return value;
- }
- /**
- * 刪除指定key的快取
- * @param prefix
- * @param key
- */
- public void deleteWithPrefix(String prefix, String key) {
- jedisCluster.del(prefix + KEY_SPLIT + key);
- LOGGER.debug("RedisUtil:delete cache key={}", prefix + KEY_SPLIT + key);
- }
- public void delete(String key) {
- jedisCluster.del(key);
- LOGGER.debug("RedisUtil:delete cache key={}", key);
- }
- }
5>如何使用,和spring boot自帶的就很類似了
- package com.xyy.controller;
- import java.util.HashMap;
- import java.util.Map;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.ui.ModelMap;
- import org.springframework.util.StringUtils;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import org.springframework.web.servlet.ModelAndView;
- import com.danga.MemCached.MemCachedClient;
- import com.xyy.model.Favorite;
- import com.xyy.service.FavoriteService;
- import com.xyy.util.JsonUtil;
- import com.xyy.util.cached.redis.XyyRedisTemplate;
- /**
- * Favorite控制層
- * @ClassName: FavoriteController
- * @author wujing
- * @date 2017-07-13 15:09:50
- */
- @RestController
- @RequestMapping("/favorite")
- public class FavoriteController{
- private static final Logger LOGGER = LoggerFactory.getLogger(FavoriteController.class);
- @Autowired
- private FavoriteService favoriteService;
- @Autowired
- private MemCachedClient memCachedClient ;
- @Autowired
- private RedisTemplate redisTemplate;
- @Autowired
- private XyyRedisTemplate xyyRedisTemplate;
- /**
- * Favorite編輯
- * @Title: update
- * @param favorite 修改物件
- * @return Object
- * @author wujing
- * @date 2017-07-13 15:09:50
- */
- //@RequestMapping("/detail2/{id}")
- public Object detail2(@PathVariable Long id,ModelMap modelMap) {
- Map<String,Object>resultMap = new HashMap<String,Object>();
- try {
- Favorite tempFavorite = favoriteService.selectByPrimaryKey(id);
- resultMap.put("status", "success");
- resultMap.put("data", tempFavorite);
- } catch (Exception e) {
- resultMap.put("status", "error");
- resultMap.put("errorMsg", "系統異常");
- LOGGER.error("Favorite新增異常", e);
- }
- return resultMap;
- }
- @RequestMapping("/detail/{id}")
- public Object detail(@PathVariable Long id,ModelMap modelMap) {
- try {
- /*Favorite tempFavorite = (Favorite) memCachedClient.get("favorite:"+id);
- if(tempFavorite == null) {
- tempFavorite = favoriteService.selectByPrimaryKey(id);
- memCachedClient.set("favorite:"+id, tempFavorite);
- }*/
- /*ValueOperations<String, Favorite>operations = redisTemplate.opsForValue();
- Favorite tempFavorite = operations.get("favorite:"+id);
- if(tempFavorite == null) {
- tempFavorite = favoriteService.selectByPrimaryKey(id);
- operations.set("favorite:"+id, tempFavorite);
- }*/
- Favorite tempFavorite = null;
- String value = xyyRedisTemplate.get("favorite",String.valueOf(id));
- if(StringUtils.isEmpty(value)) {
- tempFavorite = favoriteService.selectByPrimaryKey(id);
- xyyRedisTemplate.set("favorite",String.valueOf(id), JsonUtil.objToString(tempFavorite));
- }else {
- tempFavorite = JsonUtil.stringToObj(value, Favorite.class);
- }
- modelMap.put("tempFavorite", tempFavorite);
- } catch (Exception e) {
- LOGGER.error("Favorite查詢異常", e);
- }
- return new ModelAndView("favorite/detail");
- }
- }
JsonUtil工具包,為公司自定義檔案,這個就不公開了,可以自行採用各種json包來解析....
redis整合,在這裡,也將告一段落了,有什麼疑問歡迎留言!