Redis7整合Springboot
前言
Springboot整合Redis相关工具的发展流程
Jedis简介
简单来说,Jedis就是Redis官方推荐的Java连接开发工具。
在Java中,Redis对应于Jedis就相当于关系数据库对应于JDBC。
jedis解决了java对于redis数据库客户端的基本操作,数据库的相关crud操作一应俱全。
jedis的问题在于我们每次使用jedis都需要重新连接数据库,要知道Redis常用来处理并发操作,如此一来就会造成不可避免的性能影响。
弊端归根结底就是缺少连接池技术。
Lettuce简介
Lettuce解决了jedis的连接池问题,相较于jedis更为成熟高效,但lettuce有一个问题, 它没有解决对集群的操作问题
RedisTemplate简介
RedisTemplate是Lettuce被纳入到Springboot大家庭的产物(本质上还是lettuce),它在lettuce的基础上解决了集群相关问题,而且包含lettuce对于单机Redis的操作,我们在工作中主要使用RedisTemplate。
RedisTemplate 实操
作者废话
本人非常不推荐在jedis,lettuce上面浪费时间去练习,笔记。各位要做的就是了解前世今生即可,就像一个java程序员不需要了解二极管为什么是半导体一样,1是面试压根不问,2是工作压根不用,3是微服务中间件实在太多,4是头发实在太少。
本文将通过一个实际的案例,我们用Springboot以及RedisTemplate来写一个可用的服务,带大家了解RedisTemplate
实操环节
大家首先保证以下几点才能开始
-
Linux防火墙的Redis服务的端口打开。
-
redis.conf的bind注释掉
-
redis保护模式关掉
-
使用ide创建一个新的Springboot项目
如果你集群已经配好了,那肯定没问题,不过配置没问题单机也不影响连接。
pom文件的相关配置
需要引入以下几条依赖
<!-- 核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
他就是Springboot整合出来的对于Redis连接所需要的所有工具的合集,一条
依赖搞定!(内部包含了RedisTemplate,RedisTemplate内部又整合lettuce)
<!-- apache的连接池技术 底层连接池需要-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- swaggerUI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
连接单机Redis
yum或properties配置
spring.redis.database=0 //连接的数据库
spring.redis.host=Redis服务ip
spring.redis.port=端口
spring.redis.password=连接密码
spring.redis.lettuce.pool.max-active=8 //最大连接保持数
spring.redis.lettuce.pool.min-idle=0 //最小连接数
spring.redis.lettuce.pool.max-idle=8 //最大连接数
spring.redis.lettuce.pool.max-wait=-1ms //最大等待时长,-1ms表示无限等待
RedisTemplate的常用API
@Service
@Log4j2
public class testRedisService {
@Resource
RedisTemplate redisTemplate;
//订单头
public static final String ORDER_HEAD = "ord:";
//添加订单
public void setOrder(){
//ThreadLocalRandom.current.nextInt 保证多线程时数字的唯一性
int orderInt = ThreadLocalRandom.current().nextInt(1000)+1;
// 订单编号信息
String orderValue = "京东"+UUID.randomUUID().toString();
String key = ORDER_HEAD+orderInt;
redisTemplate.opsForValue().set(key,orderValue);
//打印信息
log.info("key: {} value: {}",key,orderValue);
}
//获取订单信息
public String getOrder(String orderId){
return (String)redisTemplate.opsForValue().get(ORDER_HEAD+orderId);
}
}
在上面的代码中,我简单的写了2个Service,我通过RedisTemplate对象的opsForValue方法,再调用set方法,向我们配置好的Redis数据库设置了一条String类型的订单号,该订单号的key我使用一个常量作为前缀,后面跟上一个随机数。value则采用uuid。
opsForValue方法是专门给String类型使用的,通过后面跟上set跟get方法来定义获取或者设置。
至于其他方法我就不再赘述了,因为RedisTemplate对象所提供的的方法除了上面所讲的opsForValue方法外,简直是一目了然,用法也基本相同。
RedisTemplate的乱码问题
如果你已经按照配置正确写好了相关的Controller,并使用swagger或postman测试接口,你会发现。当不使用中文作为key或者value时,没有任何问题,但如果有中文,则会出现乱码。
这是因为RedisTemplate在向Redis传输我们的值时,使用了默认的序列化策略, 点开RedisTemplate方法,就能看到
从上面可以看到,它在enableDefaultSerializer(使用默认序列化)这一行设置为true 而在下面的defaultSerializer上,他却没有赋值!
根据上文所说,defaultSerializer没有赋值,那么他在上图中的多个if中,自然就会进入第一个if,这就导致了它使用了jdk自带的序列化,我们不需要了解这个序列化,我们只需要知道,这个策略导致了给Redis服务器的数据出现了编码问题.
所以,我们这里就会产生2种解决方案
-
给默认的defaultSerializer赋值,给他一个不会乱码的策略。
-
使用RedisTemplate的子类StringRedisTemplate 个人主推
StringRedisTemplate
StringRedisTemplate的用法非常简单,只需要把代码中的RedisTemplate换成StringRedisTemplate就行了,别的地方全部一样,而且StringRedisTemplate的opsForValue的get方法返回值直接就是String,无需类型转换!
手动设置默认序列化
第一种方法阳哥演示了操作方法,解释了大概原理,但讲的实在笼统,其中使用到的几个序列化方法,没有讲到。让人似乎知其所以然,其实还是不懂,其主要原因还是该部分知识牵涉东西太广,彻底搞懂没有必要,半懂不懂让人很不舒服。所以这里不再演示,建议大家看视频学习,其实工作中,大家基本都使用StringRedisTemplate,不会错。
Springboot连接集群
其实并不是说配置了集群后,lettuce就无法连接了,而是说,一旦有master发生故障(这时集群会自发进行主从切换),而lettuce无法感知。
也就是说,lettuce并不知道原来的master已经被替换,所以lettuce会依旧向故障的master主机地址发送数据,进而导致服务不可用。
故障测试方法
我们可以在集群启动后手动使一台master下线(shutdown)。然后再次发送get请求查找Redis数据。(结果是没有应答,一直转圈,最终超时!)
解决方案
我们需要在RedisTemplate的配置文件中加上新的配置,让RedisTemplate通过刷新Redis集群节点来监测集群状态。
spring.redis.password=密码
#获取失败最大重定向次数
spring.redis.cluster.max-redirects=3
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
\#支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新,默认fāLse关闭
spring.redis.lettuce.cluster.refresh.adaptive=true
\#定时刷新
spring.redis.lettuce.cluster.refresh.period=2000
spr1ng.redis.c1 uster.n0des=例如192.168.111.185:6381,192.168.111.185:6382,192.168.111.172:6383,192.168.111.172:6384,
注意,上面的ip只是实例,排列规则为
主从,主从,主从 格式为ip:端口。
不要无脑复制粘贴,哪一组在前不重要,但一定是 主机+从机 为一组。
集群的操作按照API指示基于 Redis客户端的操作逻辑 正常操作即可!
转载自:https://juejin.cn/post/7243726862635548731