Springboot2.0x整合redis lettuce 和并且进行数据缓存机制。经过多问题方面的整合(单机模式)
程序员文章站
2022-03-02 18:14:43
...
整合策略参考https://blog.csdn.net/weixin_36586564/article/details/86002413
缓存策略参考https://blog.csdn.net/zhangcongyi420/article/details/82686702
问题异常参考https://blog.csdn.net/zhaoheng314/article/details/81564166
根据多方面的精华 整合好redis 代码如下
-
配置文件
# Redis服务器地址
spring.redis.host=
# Redis服务器连接密码(默认为空)
spring.redis.password=
# Redis服务器连接端口 默认6379
spring.redis.port=
# 连接超时时间(10毫秒)
spring.redis.timeout=
# Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0 1是dev环境参数
spring.redis.database=
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
-
配置依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring2.0集成redis所需common-pool2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.5.0</version>
</dependency>
<!-- 将作为Redis对象序列化器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
-
配置类
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
/**
* 自定义Template
* 默认情况下的模板只能支持RedisTemplate<String, String>,
* 也就是只能存入字符串,这在开发中是不友好的,所以自定义模板是很有必要的,
* 当自定义了模板又想使用String存储这时候就可以使用StringRedisTemplate的方式,它们并不冲突…
*
* @author king
* @since 2019/8/8
*/
@EnableCaching
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheAutoConfiguration {
@SuppressWarnings("rawtypes")
@Bean
public RedisTemplate<Object, Object> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//使用fastjson序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
// key的序列化采用StringRedisSerializer key 必须先设置
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
template.setConnectionFactory(redisConnectionFactory);
return template;
}
//缓存管理器
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager
.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory);
return builder.build();
}
}
-
工具类
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
/**
* redis 操作类
* @author kingxt
* @date 2019年8月9日
*
*/
@Component
public class RedisComponentUtils{
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 写入缓存
* @param key
* @param value
* @return boolean
*/
public boolean set(String key, Object value) {
boolean result = false;
redisTemplate.opsForValue().set(key, value);
result = true;
return result;
}
/**
* 写入缓存设置时效时间
* @param key
* @param value
* @return boolean
*/
public boolean set(String key, Object value, Long expireTime) {
boolean result = false;
ValueOperations<String, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
return result;
}
/**
* 批量删除对应的value
* @param keys
*/
public void remove(String... keys) {
for (String key : keys) {
remove(key);
}
}
/**
* 批量删除key
* @param pattern
*/
public void removePattern(String pattern) {
Set<String> keys = redisTemplate.keys(pattern);
if (keys.size() > 0)
redisTemplate.delete(keys);
}
/**
* 删除对应的value
* @param key
*/
public void remove(String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* 判断缓存中是否有对应的value
* @param key
* @return
*/
public boolean exists(String key) {
return redisTemplate.hasKey(key);
}
/**
* 读取缓存
* @param key
* @return
*/
public Object get(String key) {
Object result = null;
ValueOperations<String, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
/**
* 哈希 添加
* @param key
* @param hashKey
* @param value
*/
public void hmSet(String key, Object hashKey, Object value){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
hash.put(key,hashKey,value);
}
/**
* 哈希获取数据
* @param key
* @param hashKey
* @return
*/
public Object hmGet(String key, Object hashKey){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
return hash.get(key,hashKey);
}
/**
* 列表添加
* @param k
* @param v
*/
public void lPush(String k,Object v){
ListOperations<String, Object> list = redisTemplate.opsForList();
list.rightPush(k,v);
}
/**
* 列表获取
* @param k
* @param l
* @param l1
* @return
*/
public List<Object> lRange(String k, long l, long l1){
ListOperations<String, Object> list = redisTemplate.opsForList();
return list.range(k,l,l1);
}
/**
* 集合添加
* @param key
* @param value
*/
public void setArray(String key,Object value){
SetOperations<String, Object> set = redisTemplate.opsForSet();
set.add(key,value);
}
/**
* 集合获取
* @param key
* @return
*/
public Set<Object> getArray(String key){
SetOperations<String, Object> set = redisTemplate.opsForSet();
return set.members(key);
}
/**
* 有序集合添加
* @param key
* @param value
* @param scoure
*/
public void zAdd(String key,Object value,double scoure){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.add(key,value,scoure);
}
/**
* 有序集合获取
* @param key
* @param scoure
* @param scoure1
* @return
*/
public Set<Object> rangeByScore(String key,double scoure,double scoure1){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
return zset.rangeByScore(key, scoure, scoure1);
}
}
-
缓存策略
缓存策略参考https://blog.csdn.net/zhangcongyi420/article/details/82686702
一般的认为 需要不影响当前的业务逻辑
比如删除,更新,新增数据的时候应该删除redis中的key
比如在 缓存中如果查询不到 需要到数据库中查询,并放入缓存中
一般数据都有过期时间需要配置
1.测试用例
必须实现Serializable
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = -1L;
private Long id;
private String username;
private String password;
public User(Long id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import com.az.ugc.utils.RedisComponentUtils;
import com.az.ugc.utils.UGCDictUtils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
import javax.annotation.Resource;
/**
* @author king 测试类
* @since 20190808
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes=RedisTest.class)
@SpringBootApplication
public class RedisTest {
private static final Logger log = LoggerFactory.getLogger(RedisTest.class);
@Resource
private RedisTemplate<String,Object> redisCacheTemplate;
@Resource
private RedisComponentUtils redisService;
@Test
public void get() {
// TODO 测试线程安全
ExecutorService executorService = Executors.newFixedThreadPool(1000);
IntStream.range(0, 1000).forEach(i ->
executorService.execute(() -> redisCacheTemplate.opsForValue().increment("kk", 1))
);
redisCacheTemplate.opsForValue().set("k1", "v1");
final String k1 = (String) redisCacheTemplate.opsForValue().get("k1");
log.info("[字符缓存结果] - [{}]", k1);
log.info("[字符缓存Null结果] - [{}]", redisCacheTemplate.opsForValue().get("k111"));
// TODO 以下只演示整合,具体Redis命令可以参考官方文档,Spring Data Redis 只是改了个名字而已,Redis支持的命令它都支持
String key = UGCDictUtils.REDIS_ARTICLE_BANNER_CONDTION_KEY;
redisCacheTemplate.opsForValue().set(key, new User(1L, "u1", "pa"));
// TODO 对应 String(字符串)
log.info("获取结果:{}",redisCacheTemplate.opsForValue().get(key));;
User user = UGCDictUtils.convert(redisCacheTemplate.opsForValue().get(key).toString(), User.class) ;
// User user = (User) redisCacheTemplate.opsForValue().get(key); 这个也可以用
log.info("[对象缓存结果] - [{}]", user);
log.info("[对象缓存Null结果] - [{}]", redisCacheTemplate.opsForValue().get("13"));
// service中获取
log.info("service Info:{}",redisService.get("key").toString());
}
我使用的是fastjson
下一篇: 使用jar命令查看搜索jar包中的文件