redis是一个目前非常流行的缓存数据库,具体技术细节这里就不做描述了,下面说下干货,怎么实际应用
目前项目都使用spring boot来实现了,SO 我也来点新鲜的,说实话确实好使。
先说下使用的依赖
org.springframework.boot
spring-boot-starter-data-redis
com.alibaba
fastjson
org.springframework.boot
spring-boot-configuration-processor
true
1、基本配置,这个不管用配置文件还是config都少不了的,在这里我学习了spring boot的特性,。就是做了个底层包,在公司项目只要加载了这个包就默认启动redis。
目前redis 有sentinel cluster两种模式,下面贴代码
sentinel配置类
package com.ecej.nove.redis.config;
import java.util.HashSet;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;
/**
*
* @author QIANG
*
*/
@Configuration
@EnableConfigurationProperties(EcejRedisProperties.class)
@ConditionalOnProperty(name = "ecej.redis.sentinel")
public class RedisSentinelConfig {
private Logger LOG = LoggerFactory.getLogger(RedisSentinelConfig.class);
@Resource
private EcejRedisProperties redisProperties;
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(redisProperties.getMaxIdle());
jedisPoolConfig.setMaxTotal(redisProperties.getMaxTotal());
jedisPoolConfig.setMaxWaitMillis(redisProperties.getMaxWaitMillis());
return jedisPoolConfig;
}
public RedisSentinelConfiguration jedisSentinelConfig() {
String[] hosts = redisProperties.getHostName().split(",");
HashSet sentinelHostAndPorts = new HashSet<>();
for (String hn : hosts) {
sentinelHostAndPorts.add(hn);
}
return new RedisSentinelConfiguration(redisProperties.getMastername(), sentinelHostAndPorts);
}
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(jedisSentinelConfig(),
jedisPoolConfig());
if (!StringUtils.isEmpty(redisProperties.getPassword()))
jedisConnectionFactory.setPassword(redisProperties.getPassword());
return jedisConnectionFactory;
}
@Bean
public RedisTemplate redisTemplate() {
RedisTemplate redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
LOG.info("create redisTemplate success");
return redisTemplate;
}
}
下面贴出cluster配置
package com.ecej.nove.redis.config;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisClusterNode;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;
/**
*
* @author QIANG
*
*/
@Configuration
@EnableConfigurationProperties(EcejRedisProperties.class)
@ConditionalOnProperty(name = "ecej.redis.cluster")
public class RedisClusterConfig {
private Logger LOG = LoggerFactory.getLogger(RedisClusterConfig.class);
@Resource
private EcejRedisProperties redisProperties;
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(redisProperties.getMaxIdle());
jedisPoolConfig.setMaxTotal(redisProperties.getMaxTotal());
jedisPoolConfig.setMaxWaitMillis(redisProperties.getMaxWaitMillis());
return jedisPoolConfig;
}
public RedisClusterConfiguration redisClusterConfiguration() {
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
String[] hosts = redisProperties.getHostName().split(":");
Set redisNodes = new HashSet<>();
redisNodes.add(new RedisClusterNode(hosts[0], Integer.valueOf(hosts[1])));
redisClusterConfiguration.setClusterNodes(redisNodes);
redisClusterConfiguration.setMaxRedirects(redisProperties.getMaxRedirects());
return redisClusterConfiguration;
}
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration(),
jedisPoolConfig());
if (!StringUtils.isEmpty(redisProperties.getPassword()))
jedisConnectionFactory.setPassword(redisProperties.getPassword());
return jedisConnectionFactory;
}
@Bean
public RedisTemplate redisTemplate() {
RedisTemplate redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
LOG.info("create RedisTemplate success");
return redisTemplate;
}
}
使用的配置类,用于加载参数
package com.ecej.nove.redis.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
*
* @author QIANG
*
*/
@ConfigurationProperties(prefix = "ecej.redis")
public class EcejRedisProperties {
/**
* Max number of "idle" connections in the pool. Use a negative value to
* indicate an unlimited number of idle connections.
*/
private int maxIdle = 10;
/**
* 最大连接数
*/
private int maxTotal = 500;
private int maxWaitMillis = 3000;
private String hostName = "localhost";
private String password;
/**
* Maximum number of redirects to follow when executing commands across the
* cluster.
*/
private int maxRedirects = 10;
private String mastername;
public int getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public int getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(int maxTotal) {
this.maxTotal = maxTotal;
}
public int getMaxWaitMillis() {
return maxWaitMillis;
}
public void setMaxWaitMillis(int maxWaitMillis) {
this.maxWaitMillis = maxWaitMillis;
}
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getMaxRedirects() {
return maxRedirects;
}
public void setMaxRedirects(int maxRedirects) {
this.maxRedirects = maxRedirects;
}
public String getMastername() {
return mastername;
}
public void setMastername(String mastername) {
this.mastername = mastername;
}
}
怎么使用呢,下面编写了使用的快捷方法
package com.ecej.nove.redis.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
/**
*
* @author QIANG
*
*/
public class JedisClusterUtils {
@Resource
private RedisTemplate redisTemplate;
private static JedisClusterUtils cacheUtils;
@PostConstruct
public void init() {
cacheUtils = this;
cacheUtils.redisTemplate = this.redisTemplate;
}
/**
* 将数据存入缓存
*
* @param key
* @param val
* @return
*/
public static void saveString(String key, String val) {
ValueOperations vo = cacheUtils.redisTemplate.opsForValue();
vo.set(key, val);
}
/**
* 将数据存入缓存的集合中
*
* @param key
* @param val
* @return
*/
public static void saveToSet(String key, String val) {
SetOperations so = cacheUtils.redisTemplate.opsForSet();
so.add(key, val);
}
/**
*
*
* @param key
* 缓存Key
* @return keyValue
* @author:mijp
* @since:2017/1/16 13:23
*/
public static String getFromSet(String key) {
return cacheUtils.redisTemplate.opsForSet().pop(key);
}
/**
* 将 key的值保存为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。 SETNX 是『SET
* if Not eXists』(如果不存在,则 SET)的简写。
* 保存成功,返回 true
* 保存失败,返回 false
*/
public static boolean saveNX(String key, String val) {
/** 设置成功,返回 1 设置失败,返回 0 **/
return cacheUtils.redisTemplate.execute((RedisCallback) connection -> {
return connection.setNX(key.getBytes(), val.getBytes());
});
}
/**
* 将 key的值保存为 value ,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。 SETNX 是『SET
* if Not eXists』(如果不存在,则 SET)的简写。
* 保存成功,返回 true
* 保存失败,返回 false
*
* @param key
* @param val
* @param expire
* 超时时间
* @return 保存成功,返回 true 否则返回 false
*/
public static boolean saveNX(String key, String val, int expire) {
boolean ret = saveNX(key, val);
if (ret) {
cacheUtils.redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
return ret;
}
/**
* 将数据存入缓存(并设置失效时间)
*
* @param key
* @param val
* @param seconds
* @return
*/
public static void saveString(String key, String val, int seconds) {
cacheUtils.redisTemplate.opsForValue().set(key, val, seconds, TimeUnit.SECONDS);
}
/**
* 将自增变量存入缓存
*/
public static void saveSeq(String key, long seqNo) {
cacheUtils.redisTemplate.delete(key);
cacheUtils.redisTemplate.opsForValue().increment(key, seqNo);
}
/**
* 将递增浮点数存入缓存
*/
public static void saveFloat(String key, float data) {
cacheUtils.redisTemplate.delete(key);
cacheUtils.redisTemplate.opsForValue().increment(key, data);
}
/**
* 保存复杂类型数据到缓存
*
* @param key
* @param obj
* @return
*/
public static void saveBean(String key, Object obj) {
cacheUtils.redisTemplate.opsForValue().set(key, JSON.toJSONString(obj));
}
/**
* 保存复杂类型数据到缓存(并设置失效时间)
*
* @param key
* @param Object
* @param seconds
* @return
*/
public static void saveBean(String key, Object obj, int seconds) {
cacheUtils.redisTemplate.opsForValue().set(key, JSON.toJSONString(obj), seconds, TimeUnit.SECONDS);
}
/**
* 功能: 存到指定的队列中
* 左近右出
作者: 耿建委
*
* @param key
* @param val
* @param size
* 队列大小限制 0:不限制
*/
public static void saveToQueue(String key, String val, long size) {
ListOperations lo = cacheUtils.redisTemplate.opsForList();
if (size > 0 && lo.size(key) >= size) {
lo.rightPop(key);
}
lo.leftPush(key, val);
}
/**
* 保存到hash集合中
*
* @param hName
* 集合名
* @param key
* @param val
*/
public static void hashSet(String hName, String key, String value) {
cacheUtils.redisTemplate.opsForHash().put(hName, key, value);
}
/**
* 根据key获取所以值
*
* @param key
* @return
*/
public static Map
2、重点来了,我们怎么叫我们的jar包加入自启动呢?首先加入autoconfig
package com.ecej.nove.redis.core;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import com.ecej.nove.redis.config.RedisClusterConfig;
import com.ecej.nove.redis.config.RedisSentinelConfig;
import com.ecej.nove.redis.utils.JedisClusterUtils;
@Configuration
@Import({ RedisClusterConfig.class, RedisSentinelConfig.class, JedisClusterUtils.class })
public class RedisAutoConfiguration {
}
在src\main\resources下面增加自启动扫描配置
META-INF/spring.factories
Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.ecej.nove.redis.core.RedisAutoConfiguration
3、至此,配置就全部完成了,下面说下使用
说下Redis使用,如果想在自己的项目中使用redis,如下先加入依赖
就可以了,然后我们只要配置我们的配置文件,不需要其他多余的工作
redis集群分为两种,sentinel 还有3.x的cluster,根据你自己的需要选择集群配置,配置文件都放在resources下面的
先说sentinel配置
用法:使用com.xxx.nove.redis.utils.JedisClusterUtils这个静态类
remote-redis.properties
这个大家可以直接下载用
[email protected]@
[email protected]@
[email protected]@
以下配置可选择增加
[email protected]@
[email protected]@
[email protected]@
这是properties的配置
下面说下POM里面profile的配置
下面再说下3.x的配置
remote-redis.properties
[email protected]@
[email protected]@
以下配置可选择增加
[email protected]@
[email protected]@
[email protected]@
[email protected]@
下面贴出profile的配置
两种配置都有了,那下面说下怎么选择用哪种集群模式
xxx.redis.cluster=true 使用3.x模式
xxx.redis.sentinel=true 使用sentinel模式
注意:这俩配置选一个,放在application.properties中,不要乱放。
OK,全部配置完成,可以开心的使用了
关注公众号,将获得最新文章推送