SpringBoot 集成Redis Cluster和RedisTemplate

邓才
2023-12-01

先看示例:

// 将验证码放入缓存,并设置自动过期时间
CacheUtils.put(CacheKey.PHONE_VERIFY_CODE.key(phone), code, 1, TimeUnit.HOURS);

// 从缓存中获取验证码
String code = CacheUtils.get(CacheKey.PHONE_VERIFY_CODE.key(phone));

// 删除缓存
CacheUtils.del(CacheKey.PHONE_VERIFY_CODE.key(phone));

缓存使用注意事项:

1、缓存尽量设置一个过期时间

2、相关联的数据尽量用redis的HashMap结构存储,这样主动删除所有的时候,不需要使用模糊删除,模糊查询效率比较低,很占CPU

3、缓存value尽量用JSON字符串存储,因为我们遇到一个坑,直接存储对象,当对象中某些实体类属性包路径改变的时候,原来的数据反序列会报错。

下面是一些配置和工具类:

RedisClusterConfig.java


import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.MapPropertySource;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import redis.clients.jedis.JedisPoolConfig;

/**
 * 
 * 
 * @Description: redis集群配置
 */
@Configuration
@EnableRedisRepositories
public class RedisClusterConfig {

	@Value("${spring.redis.cluster.nodes}")
	private String clusterNodes;

	@Value("${spring.redis.cluster.timeout}")
	private Long timeout;

	@Value("${spring.redis.cluster.max-redirects}")
	private int redirects;
	@Autowired
 	private RedisPoolConfig redisPoolConfig;

	@Bean
	public RedisClusterConfiguration getClusterConfiguration() {
		Map<String, Object> config = new HashMap<String, Object>();
		config.put("spring.redis.cluster.nodes", clusterNodes.trim());
		config.put("spring.redis.cluster.timeout", timeout);
		config.put("spring.redis.cluster.max-redirects", redirects);
		return new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", config));
	}

	@Bean(name = "jedisPoolConfig")
 	public JedisPoolConfig getJedisPoolConfig(){
 		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
 		jedisPoolConfig.setMaxTotal(redisPoolConfig.getMaxTotal());
 		jedisPoolConfig.setMaxIdle(redisPoolConfig.getMaxIdle());
 		jedisPoolConfig.setMinIdle(redisPoolConfig.getMinIdle());
 		jedisPoolConfig.setMaxWaitMillis(redisPoolConfig.getMaxWaitMillis());
 		jedisPoolConfig.setTestOnBorrow(redisPoolConfig.getTestOnBorrow());
 		jedisPoolConfig.setTestWhileIdle(redisPoolConfig.getTestWhileIdle());
 		jedisPoolConfig.setTestOnReturn(redisPoolConfig.getTestOnReturn());
 		jedisPoolConfig.setBlockWhenExhausted(redisPoolConfig.getBlockWhenExhausted());
 		jedisPoolConfig.setNumTestsPerEvictionRun(redisPoolConfig.getNumTestsPerEvictionRun());
 		jedisPoolConfig.setTimeBetweenEvictionRunsMillis(redisPoolConfig.getTimeBetweenEvictionRunsMillis());
 		jedisPoolConfig.setMinEvictableIdleTimeMillis(redisPoolConfig.getMinEvictableIdleTimeMillis());
 		return jedisPoolConfig;
 	}

	public @Bean RedisConnectionFactory connectionFactory(RedisClusterConfiguration redisClusterConfig,
			@Qualifier("jedisPoolConfig") JedisPoolConfig pooConfig) {
		JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfig);
		jedisConnectionFactory.setPoolConfig(pooConfig);
		jedisConnectionFactory.setUsePool(true);
		jedisConnectionFactory.afterPropertiesSet();
		return jedisConnectionFactory;
	}

	@Bean(name = "redisTemplate")
	public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
		RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
		template.setConnectionFactory(connectionFactory);
		template.setKeySerializer(new StringRedisSerializer());
		template.setHashKeySerializer(new StringRedisSerializer());
		template.afterPropertiesSet();
		return template;
	}
}

RedisPoolConfig.java


import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * redis主从连接池配置bean
 * 
 * @author Lee
 *
 */
@ConfigurationProperties(value = "jedisPool")
public class RedisPoolConfig extends AbstractSettings {

	/**
	 * 缓存最大连接数
	 */
	private Integer maxTotal;
	/**
	 * 缓存最大空闲数
	 */
	private Integer maxIdle;
	/**
	 * 缓存最小空闲数
	 */
	private Integer minIdle;
	
	/**
	 * 最大等待空闲时间
	 */
	private Integer maxWaitMillis;
	
	private Boolean testOnBorrow;
	
	private Boolean testWhileIdle;
	
	private Boolean testOnReturn;
	
	private Boolean blockWhenExhausted;
	
	private Integer numTestsPerEvictionRun;
	
	private Integer timeBetweenEvictionRunsMillis;
	
	private Integer softMinEvictableIdleTimeMillis;
	
	
	/**
	 * 最小驱逐空闲时间
	 */
	private Integer minEvictableIdleTimeMillis;
	
	public Integer getMinEvictableIdleTimeMillis() {
		return minEvictableIdleTimeMillis;
	}

	public void setMinEvictableIdleTimeMillis(Integer minEvictableIdleTimeMillis) {
		this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
	}

	public Integer getMaxTotal() {
		return maxTotal;
	}

	public void setMaxTotal(Integer maxTotal) {
		this.maxTotal = maxTotal;
	}

	public Integer getMaxIdle() {
		return maxIdle;
	}

	public void setMaxIdle(Integer maxIdle) {
		this.maxIdle = maxIdle;
	}

	public Integer getMinIdle() {
		return minIdle;
	}

	public void setMinIdle(Integer minIdle) {
		this.minIdle = minIdle;
	}

	public Integer getMaxWaitMillis() {
		return maxWaitMillis;
	}

	public void setMaxWaitMillis(Integer maxWaitMillis) {
		this.maxWaitMillis = maxWaitMillis;
	}

	public Boolean getTestOnBorrow() {
		return testOnBorrow;
	}

	public void setTestOnBorrow(Boolean testOnBorrow) {
		this.testOnBorrow = testOnBorrow;
	}

	public Boolean getTestWhileIdle() {
		return testWhileIdle;
	}

	public void setTestWhileIdle(Boolean testWhileIdle) {
		this.testWhileIdle = testWhileIdle;
	}

	public Boolean getTestOnReturn() {
		return testOnReturn;
	}

	public void setTestOnReturn(Boolean testOnReturn) {
		this.testOnReturn = testOnReturn;
	}

	public Boolean getBlockWhenExhausted() {
		return blockWhenExhausted;
	}

	public void setBlockWhenExhausted(Boolean blockWhenExhausted) {
		this.blockWhenExhausted = blockWhenExhausted;
	}

	public Integer getNumTestsPerEvictionRun() {
		return numTestsPerEvictionRun;
	}

	public void setNumTestsPerEvictionRun(Integer numTestsPerEvictionRun) {
		this.numTestsPerEvictionRun = numTestsPerEvictionRun;
	}

	public Integer getTimeBetweenEvictionRunsMillis() {
		return timeBetweenEvictionRunsMillis;
	}

	public void setTimeBetweenEvictionRunsMillis(
			Integer timeBetweenEvictionRunsMillis) {
		this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
	}

	public Integer getSoftMinEvictableIdleTimeMillis() {
		return softMinEvictableIdleTimeMillis;
	}

	public void setSoftMinEvictableIdleTimeMillis(
			Integer softMinEvictableIdleTimeMillis) {
		this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
	}
	
}

pom.xml

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.9.0</version><!--$NO-MVN-MAN-VER$-->
</dependency>
		
<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-redis</artifactId>
	<version>1.7.6.RELEASE</version><!--$NO-MVN-MAN-VER$-->
</dependency>

application.properties

jedisPool.maxTotal=2048
jedisPool.maxIdle=200
jedisPool.minIdle=10
jedisPool.numTestsPerEvictionRun=1024
jedisPool.timeBetweenEvictionRunsMillis=30000
jedisPool.minEvictableIdleTimeMillis=-1
jedisPool.softMinEvictableIdleTimeMillis=10000
jedisPool.maxWaitMillis=1500
jedisPool.testOnBorrow=true
jedisPool.testWhileIdle=true
jedisPool.testOnReturn=false
jedisPool.blockWhenExhausted=false
#********************redis.cluster******************************************
spring.redis.cluster.nodes=
spring.redis.cluster.timeout=20000
spring.redis.cluster.max-redirects=8

CacheUtils.java


import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.joda.time.DateTime;
import org.joda.time.Seconds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.tomtop.framework.common.exception.MessageException;

@Component
public class CacheUtils{

    private static RedisTemplate<String,Serializable> redisTemplate;

    @Autowired
	public void setRedisTemplate(
			RedisTemplate<String, Serializable> redisTemplate) {
		CacheTools.redisTemplate = redisTemplate;
	}
    	
    public static void put(String key, Serializable value) {
    	if(!key.contains(":")){
    		throw MessageException.newMessageException("key需要缓存库名,比如lottery_:");
    	}
    	redisTemplate.opsForValue().set(key, value);
    }
    
    public static void put(String key, String hashKey, Serializable value) {
    	if(!key.contains(":")){
    		throw MessageException.newMessageException("key需要缓存库名,比如lottery_:");
    	}
		redisTemplate.opsForHash().put(key, hashKey, value);
    }
    
    public static void put(String key, Serializable value, long time, TimeUnit unit) {
    	if(!key.contains(":")){
    		throw MessageException.newMessageException("key需要缓存库名,比如lottery_:");
    	}
		redisTemplate.opsForValue().set(key, value, time, unit);
    }

    @SuppressWarnings("unchecked")
	public static <T>T get(String key) {
    	try{
    		return (T)redisTemplate.opsForValue().get(key);
    	}catch(Exception e){
    		e.printStackTrace();
    	}
    	return null;
    }
    
    @SuppressWarnings("unchecked")
	public static <T>T get(String key, String hashKey){
    	return (T) redisTemplate.opsForHash().get(key, hashKey);
    }
    
    public static void expireAt(String key, Date date){
    	int seconds = Seconds.secondsBetween(new DateTime(), new DateTime(date)).getSeconds();
    	redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
	}
    
    public static void del(String key) {
		redisTemplate.delete(key);
    }
    
    /**
     * 次日凌晨时间过期
     * @param key
     */
    public static void expireAtMorrowZero(String key){
    	expireAt(key, morrowZero());
	}
	
	/**
	 * 次日凌晨时间
	 * 
	 */
    public static Date morrowZero(){
		Calendar c = Calendar.getInstance();
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.MILLISECOND, 0);
		c.add(Calendar.DAY_OF_MONTH, 1);
		return c.getTime();
	}
}

CacheKey.java

/**
 * 缓存key
 */
public enum CacheKey {
	
	/**
	 * CART缓存公用前缀
	 */
	PREFIX_CART("cart_:"),
	/**
	 * ORDER缓存公用前缀
	 */
	PREFIX_ORDER("order_:"),
//	-------------------------------------------------------------CART配置缓存key-----------------------------------------------------
	PHONE_VERIFY_CODE(PREFIX_CART+"phone_verify_code_#{phone}"), // 手机验证码
	
//	-------------------------------------------------------------ORDER配置缓存key-----------------------------------------------------
	DYNAMIC_MSG_KEY(PREFIX_ORDER+"dynamic_msg_#{code}_#{spu}"), // 动态消息
	;
	
	private String name;

	private CacheKey(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}
	
	public String key(Object ... args){
		String result = name;
		for(Object arg : args){
			if(arg!=null){
				result = result.replaceFirst("#\\{\\w*\\}", String.valueOf(arg));
			}
		}
		return result;
	}

	@Override
	public String toString() {
		return name;
	}
	
}

 

 类似资料: