springboot 集成 redis使用实践
2021-03-03 本文已影响0人
Geroge1226
1、背景介绍
Redis
作为缓存工具,大部分项目中会经常用到。为方便以后快速集成Redis
,现将SpringBoot 集成Redis
实践过程记录如下。
2、springboot 集成redis步骤
1、pom包引入Redis依赖
<!-- 引用Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
# 注意:
<!--这里我使用的springboot 2.2.1-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath />
</parent>
2、yml文件配置Redis相关
spring:
application:
name: redis-demo
redis:
host: localhost
database: 1
jedis: # 配置jedis线程池,也可以配置Lettuce
pool:
max-active: 8 # 最大活动数量()
max-wait: -1 # 连接池最大阻塞时间 (使用负数表示没有限制)
port: 6379 # 6379默认端口,不配置就取默认
# --lettuce 配置
# lettuce:
# pool:
# max-active:
注:
这里可以选用redis 的lettuce
client端。配置和 jedis
一致。
3、编写RedisConfig配置类
/**
* All rights Reserved, Designed By www.pousheng.com
*
* @version V1.0
* @Title: RedisConfig
* @Package com.lsy.redisdemo.config
* @Description: 简单描述下这个类是做什么用的
* */
@Configuration
public class RedisConfig {
/**
* @name: redisTemplate
* @description: RedisTemplate
* @param redisConnectionFactory
* @return: org.springframework.data.redis.core.RedisTemplate<java.lang.String,java.lang.Object>
* @date: 2020-12-04 13:19
*
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer(Object.class);
// 设置键(key)的序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 设置value序列化
redisTemplate.setValueSerializer(serializer);
// 设置HashKey序列化 为啥要hashkey
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// 设置HashValue序列化
redisTemplate.setHashValueSerializer(serializer);
// 默认序列化
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
return redisTemplate;
}
}
到这里,简单Redis集成
已经完成了,使用到地方,直接@Autowired
redisTemplate 即可。
@Autowired
private RedisTemplate redisTemplate;
接下来就将不同数据类型操作整理如下:
3、redisTemplate 对于不同数据结构的Curd举例:
redisTemplate.opsForList();//操作list
redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForCluster();//集群时使用
redisTemplate.opsForGeo();//地理位置时使用
redisTemplate.opsForHash();//操作散列
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set
redisTemplate.opsForHyperLogLog(); //操作有序set
3.1 字符串类型
opsForValue
常用方法说明如下:
-
setIfAbsent
:(absent缺席)如果键不存在则新增,如果存在则不改变已经有的值。 -
setIfPresent
: (present出席)如果键不存在则不新增,如果存在则修改。 -
append
: 在当前key
对应的value
后面追加value
。 -
increment(key, value)
: 用户值为数字加法,value值,如果value为空,则对于key自增1 -
decrement
: 用户值为数字类型的减法,value值有就减少value个单位。 -
mutiSet(map)
: 批量设置字符串键值。 -
mutiGet(Collection)
: 批量查询,返回对应批量key值的value值集合list。 -
size
: 返回键对应的值存储长度。
redisTemplate.opsForValue().setIfAbsent(key,value,timeoutR, TimeUnit.DAYS);
redisTemplate.opsForValue().setIfPresent(key,value,timeoutR, TimeUnit.DAYS);
3.2 散列类型
opsForHash()
常用方法如下:
-
putIfAbsent(key,hashkey,value)
: 追加key下的hashkey字段及对应的value值, 如果hashkey存在,则不追加value值,如果hashkey不存在则追加。 -
putAll(key,Map)
: 增加key对应的hash对象,如果key存在则修改原本hash对象,修改规则:修改map中的字段匹配到hashkey的hashvalue值,如果map中的字段无法匹配hashkey,则不会新增hashkey和hashvalue,原本hash对象中多出的hash键值对保持不变。 -
put(key,hashkey,hashvalue)
: 增加key对应hash对象字段及字段值属性,如果key存在会修改hashkey或者新增hashkey操作(hashkey不存在) -
delete(key,hashkey)
: 删除key下的hashkey,hashkey传入一个或多个。 -
values(key)
: 返回key下所有hashkey对应的hashvalue值的集合list
。
【示例】
key:123456 对应的hash对象如下:
执行putALL
方法,key:123456
Map对象值如下,与redis中已经存在的比较,减少了"mobile",增加了"birthday"。
{
"id": "123456",
"userName": "usr",
"memberId": "337462",
"birthday": "2021-06-08 16:42:01"
}
执行结果如下:
3.3 列表类型
现有列表如下:
opsForList
常用方法说明
-
range(key,start,end)
: 列表查询,返回列表:start指的是列表下标,列表第一位0开始,end列表下标(包含下标后面的元素:"( , ]" )。 -
leftpush(key,value)
: 从列表左边方式插入元素,如果key不存在则新增key对应的列表 -
leftPush(key,pivot,value)
: 查找列表中pivot元素前面插入value值 -
rightpush(key,value)
: 从列表右边方式插入元素,如果key不存在则新增key对应的列表 -
set(key,index,value)
:修改列表中index位置的元素 -
size(key)
: 列表的大小 -
rightPopAndLeftPush(key,destination)
: 从当前列表右边pop一个元素并从左边插入到 destination目标列表。
3.3 set集合型类型
opsForSet
常用方法说明:
-
add(key,value)
: 添加集合元素,如果集合不存在则新增. -
members(key)
: 列出所有集合中的元素集. -
isMember(key,member)
: 判断member是否存在集合key值中. -
intersect(key1, key2)
: 求交集,返回集合key1, key2的共有的元素集. -
difference(key1,key2)
: 求差集,返回仅存在key1中的元素集. -
union(key1,key2)
: 求并集,返回集合key1,key2中所有不重复元素集. -
remove(key , value)
: 删除集合key中的元素value. -
size(key)
: 查看集合的大小
3.4 zset有序集合类型
opsForZSet
常用方法说明
-
add(key , value, score)
: 添加有序集合,如果集合不存在则新增 -
range(key,start,stop)
: 获取redis有序集合范围类元素,按默认排序索引(分数从小到大)
4、redisTemplate中管理redis事务
RedisTemplate来操作Redis,关于事务操作的时候会有问题:
public void redisMulti(String key, Long increment){
// redis事务开启
redisTemplate.multi();
redisTemplate.opsForValue().increment(key,increment);
redisTemplate.opsForValue().increment(key,increment);
redisTemplate.opsForValue().increment(key,increment);
redisTemplate.opsForValue().increment(key,increment);
redisTemplate.exec();
}
原本以为按照如下操作redis事务,但断点在exec
地方,还未执行exec()
方法,redis客户端里就已近存有key的计算结果。当执行完毕后会报如下错误:
21-06-10 14:04:07.721 ERROR 80076 --- [nio-8081-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/redis-demo] threw exception [Request processing failed; nested exception is org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR EXEC without MULTI] with root cause
io.lettuce.core.RedisCommandExecutionException: ERR EXEC without MULTI
at io.lettuce.core.ExceptionFactory.createExecutionException(ExceptionFactory.java:135) ~[lettuce-core-5.1.7.RELEASE.jar:na]
at io.lettuce.core.ExceptionFactory.createExecutionException(ExceptionFactory.java:108) ~[lettuce-core-5.1.7.RELEASE.jar:na]
省略
原因是配置redisTemplate地方未开启事务,增加如下部分:
// 开启事务
redisTemplate.setEnableTransactionSupport(true);