先看示例:
// 将验证码放入缓存,并设置自动过期时间
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;
}
}