SpringBoot整合redis集群

       我负责的项目中用到了redis,因为是单人负责整个项目,所以只能去网上找相关的资料和文档,现在项目上线,将相关配置记录下,方便自己以后查阅,也希望能给其他同学带来参考和帮助。

       springBoot2.0以后版本做了重大更新,本博客基于的是1.5.10版本,不适用于2.0以上的版本,所以请大家注意下。jdk版本是1.8,redis集群是公司运维的同学搭建的,所以在此不讨论redis集群的版本号和配置问题。

 

首先先引入相关的pom配置,官方提供了redis集群的配置,所以不需要做过多的引入:

		
			org.springframework.boot
			spring-boot-starter-data-redis
                        1.5.10.RELEASE
		

version版本号可以自定义,也可以根据你的springBoot版本走,这里是为了给大家看的清楚,写死了版本号

然后是redis的配置文件:


import java.util.HashSet;
import java.util.Set;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

/**
 * ClassName: JedisClusterConfig 
 * Description: 
 * @date 2018年4月3日  
 */
@Configuration
public class JedisClusterConfig {
	
	private static final Logger log = LoggerFactory.getLogger(JedisClusterConfig.class);

	@Value("${redis.nodes}")
	private String nodes;
 
	@Value("${redis.commandTimeout}")
	private int commandTimeout;
	
	@Value("${redis.pwd}")
	private String pwd;
	
	@Value("${redis.maxTotal}")
	private int maxTotal;
	
	@Value("${redis.maxIdle}")
	private int maxIdle;
	
	@Value("${redis.minIdle}")
	private int minIdle;
	
	@Value("${redis.maxWait}")
	private int maxWait;
	
    /**
     * 注意:
     * 这里返回的JedisCluster是单例的,并且可以直接注入到其他类中去使用
     * @return
     */
    @Bean
    public JedisCluster getJedisCluster() {
    	 log.info("进入redis集群初始化方法:访问集群地址为:"+nodes);
        String[] serverArray = nodes.split(",");//获取服务器数组(这里要相信自己的输入,所以没有考虑空指针问题)
        Set nodes = new HashSet<>();
        for (String ipPort : serverArray) {
            String[] ipPortPair = ipPort.split(":");
            nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));
        }
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setMaxTotal(maxTotal);
        config.setMaxIdle(maxIdle);
        config.setMinIdle(minIdle);//设置最小空闲数
        config.setMaxWaitMillis(maxWait);
	//在获取Jedis连接时,自动检验连接是否可用
	config.setTestOnBorrow(true);
	//在将连接放回池中前,自动检验连接是否有效
	config.setTestOnReturn(true);
	//自动测试池中的空闲连接是否都是可用连接
	config.setTestWhileIdle(true);
	//连接耗尽时是否阻塞, false报异常,ture阻塞直到超时,默认true
	config.setBlockWhenExhausted(false);
        //表示idle object evitor两次扫描之间要sleep的毫秒数
        config.setTimeBetweenEvictionRunsMillis(30000);
        //表示idle object evitor每次扫描的最多的对象数
        config.setNumTestsPerEvictionRun(10);
        //表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
        config.setMinEvictableIdleTimeMillis(60000);
        //需要密码连接的创建对象方式
        //参数依次是:集群地址,链接超时时间,返回值的超时时间,链接尝试次数,密码和配置文件
        return new JedisCluster(nodes,commandTimeout,10000,3,pwd,config);
    }
    
}

这里提供的是最全的JedisCluster实例化方法,所有的参数都传入,如果你并不需要传入这么多参数,JedisCluster还提供了其他方法,包括集群的和单点的都有,可以根据需求自己配置:


  public JedisCluster(HostAndPort node) {
	this(Collections.singleton(node), DEFAULT_TIMEOUT);
  }

  public JedisCluster(HostAndPort node, int timeout) {
    this(Collections.singleton(node), timeout, DEFAULT_MAX_REDIRECTIONS);
  }

  public JedisCluster(HostAndPort node, int timeout, int maxAttempts) {
    this(Collections.singleton(node), timeout, maxAttempts, new GenericObjectPoolConfig());
  }

  public JedisCluster(HostAndPort node, final GenericObjectPoolConfig poolConfig) {
    this(Collections.singleton(node), DEFAULT_TIMEOUT, DEFAULT_MAX_REDIRECTIONS, poolConfig);
  }

  public JedisCluster(HostAndPort node, int timeout, final GenericObjectPoolConfig poolConfig) {
    this(Collections.singleton(node), timeout, DEFAULT_MAX_REDIRECTIONS, poolConfig);
  }

  public JedisCluster(HostAndPort node, int timeout, int maxAttempts,
      final GenericObjectPoolConfig poolConfig) {
    this(Collections.singleton(node), timeout, maxAttempts, poolConfig);
  }

  public JedisCluster(HostAndPort node, int connectionTimeout, int soTimeout,
      int maxAttempts, final GenericObjectPoolConfig poolConfig) {
    super(Collections.singleton(node), connectionTimeout, soTimeout, maxAttempts, poolConfig);
  }

  public JedisCluster(HostAndPort node, int connectionTimeout, int soTimeout,
                      int maxAttempts, String password, final GenericObjectPoolConfig poolConfig) {
    super(Collections.singleton(node), connectionTimeout, soTimeout, maxAttempts, password, poolConfig);
  }
  
  public JedisCluster(Set nodes) {
    this(nodes, DEFAULT_TIMEOUT);
  }

  public JedisCluster(Set nodes, int timeout) {
    this(nodes, timeout, DEFAULT_MAX_REDIRECTIONS);
  }

  public JedisCluster(Set nodes, int timeout, int maxAttempts) {
    this(nodes, timeout, maxAttempts, new GenericObjectPoolConfig());
  }

  public JedisCluster(Set nodes, final GenericObjectPoolConfig poolConfig) {
    this(nodes, DEFAULT_TIMEOUT, DEFAULT_MAX_REDIRECTIONS, poolConfig);
  }

  public JedisCluster(Set nodes, int timeout, final GenericObjectPoolConfig poolConfig) {
    this(nodes, timeout, DEFAULT_MAX_REDIRECTIONS, poolConfig);
  }

  public JedisCluster(Set jedisClusterNode, int timeout, int maxAttempts,
      final GenericObjectPoolConfig poolConfig) {
    super(jedisClusterNode, timeout, maxAttempts, poolConfig);
  }

  public JedisCluster(Set jedisClusterNode, int connectionTimeout, int soTimeout,
      int maxAttempts, final GenericObjectPoolConfig poolConfig) {
    super(jedisClusterNode, connectionTimeout, soTimeout, maxAttempts, poolConfig);
  }

  public JedisCluster(Set jedisClusterNode, int connectionTimeout, int soTimeout,
                      int maxAttempts, String password, final GenericObjectPoolConfig poolConfig) {
    super(jedisClusterNode, connectionTimeout, soTimeout, maxAttempts, password, poolConfig);
  }

redis的配置文件也很简单,因为没找到redis官方的写法,所以就按照网上的写法自定义了yml注解,直接用@Value("${redis.maxIdle}")注入,也可用@ConfigurationProperties直接将参数注入到一个对象中。下面是我的yml写法,给大家提供下参考:

redis:
  nodes: 10.200.200.2:7011,10.200.200.2:7012,10.200.200.2:7013,10.200.200.2:7014,10.200.200.2:7015,10.200.200.2:7016
  commandTimeout: 10000  #redis操作的超时时间
  maxTotal: 5000 #最大连接数
  maxIdle: 30 #最大空闲连接数
  minIdle: 5 #最小空闲连接数
  maxWait: 3000  #获取连接最大等待时间 ms  #default -1
  pwd: 

因为是自定义配置,所以所有需要多环境配置的参数都可以写过来,方便部署,而redis集群的使用就更加简单了,下面是根据网上的配置自己写的util:


/**
 * ClassName: RedisUtil 
 * Description: 
 * @date 2018年4月3日  
 */
import com.alibaba.fastjson.JSON;
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;
 
@Component
public class RedisUtil {
    private static final Logger LOGGER    = LoggerFactory.getLogger(RedisUtil.class);
 
    @Autowired
    private JedisCluster  jedisCluster;
 
    /**
     * 设置缓存
     * @param key    缓存key
     * @param value  缓存value
     */
    public void set(String key, String value) {
        jedisCluster.set(key, value);
        LOGGER.debug("RedisUtil:set cache key={},value={}", key, value);
    }
 
    /**
     * 设置缓存对象
     * @param key    缓存key
     * @param obj  缓存value
     */
    public  void setObject(String key, T obj , int expireTime) {
        jedisCluster.setex(key, expireTime, JSON.toJSONString(obj));
    }
 
    /**
     * 获取指定key的缓存
     * @param key---JSON.parseObject(value, User.class);
     */
    public String getObject(String key) {
        return jedisCluster.get(key);
    }
 
    /**
     * 判断当前key值 是否存在
     *
     * @param key
     */
    public boolean hasKey(String key) {
        return jedisCluster.exists(key);
    }
 
 
    /**
     * 设置缓存,并且自己指定过期时间
     * @param key
     * @param value
     * @param expireTime 过期时间
     */
    public void setWithExpireTime( String key, String value, int expireTime) {
        jedisCluster.setex(key, expireTime, value);
        LOGGER.debug("RedisUtil:setWithExpireTime cache key={},value={},expireTime={}", key, value, expireTime);
    }
 
 
    /**
     * 获取指定key的缓存
     * @param key
     */
    public String get(String key) {
        String value = jedisCluster.get(key);
        LOGGER.debug("RedisUtil:get cache key={},value={}",key, value);
        return value;
    }
 
    /**
     * 删除指定key的缓存
     * @param key
     */
    public void delete(String from,String key) {
        jedisCluster.del(key);
        LOGGER.info("RedisUtil:delete "+from+" cache key={}", key);
    }
    
    /**
     * @Title: expire  
     * @Description: 更新key的失效时间 
     * @param key
     * @throws
     */
    public Long expire(String key,int seconds) {
    	LOGGER.debug("RedisUtil:expire cache key={}", key);
      return jedisCluster.expire(key, seconds);
    }
    
    public Long pexpire(String key,long seconds) {
    	LOGGER.debug("RedisUtil:expire cache key={}", key);
      return jedisCluster.pexpire(key, seconds);
    }
 
}

这个工具类没有过多封装只是打印了log,实际使用中可以根据情况直接注入JedisCluster对象,也可以将各种判断,序列化引入,封装的更完善。上述写法亲测有效,如果在使用中发现其他问题,可以留言,大家一起探讨。

 

 

 

 

 

 

 

 

你可能感兴趣的:(java,SpringBoot,redis)