Java使用Redis
Java使用Redis有三种技术分别是:Jedis、lettuce和RedisTemplate,其中目前主流的是RedisTemplate,其它两个面临被淘汰
一、Jedis
Jedis是Redis官方推荐的Java连接开发工具,创建springboot项目,直接导入 maven 坐标,如下pom.xml所示:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.redis7</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<jedis.version>4.3.1</jedis.version>
<lettuce-core.version>6.2.3.RELEASE</lettuce-core.version>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
</properties>
<dependencies>
<!--springboot通用依赖模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<!--通用基础配置-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
设置application.yml文件
server: port: 7777 spring: application: name: com.redis7
引入Redis 的驱动程序后,接下来就是连接 Redis 服务器。最简单的连接方式,就是通过 Jedis 对象连接。在项目创建 Demo.jedisDemo 类代码如下:
package com.redis7.demo.Demo; import lombok.extern.slf4j.Slf4j; import redis.clients.jedis.Jedis; import java.util.List; @Slf4j public class JedisDemo { public static void main(String[] args) { // 创建一个jedis连接对象 Jedis jedis = new Jedis("192.168.42.132", 6379); // 指定连接的密码 jedis.auth("123456"); log.info("redis conn status:{}","连接成功"); log.info("redis ping retvalue:{}",jedis.ping()); //设置一个字符串 jedis.set("k9090", "jedis"); log.info("k1 value:{}",jedis.get("k9090")); //列表 jedis.lpush("names", "jery"); jedis.lpush("names", "augus"); jedis.lpush("names", "tom"); // 获取存储的数据并输出 List<String> list_name = jedis.lrange("names", 0, 2); for(int i=0;i<list_name.size();i++){ System.out.println("list value:{}"+list_name.get(i)); } } }
二、Lettuce
Lettuce是一个Redis的Java驱动包,初识她的时候是使用RedisTemplate的时候遇到点问题Debug到底层的一些源码,发现spring-data-redis的驱动包在某个版本以后替换为Lettuce。Lettuce翻译为生菜,没错,就是吃的那种生菜,因此它的Logo长这样

Lettuce简介
Lettuce是一个高性能基于Java编写的Redis驱动框架,底层集成了Project Reactor提供自然的反应式编程,通讯框架集成了Netty使用了非阻塞IO,5.x版本以后融合了JDK1.8的异步编程特性,在保证高性能的同时提供了十分丰富易用的API,5.1版本的新特性以下:node
- 支持
Redis的新增命令ZPOPMIN, ZPOPMAX, BZPOPMIN, BZPOPMAX。 - 支持经过
Brave模块跟踪Redis命令执行。 - 支持
Redis Streams。 - 支持异步的主从链接。
- 支持异步链接池。
- 新增命令最多执行一次模式(禁止自动重连)。
- 全局命令超时设置(对异步和反应式命令也有效)。
- ......等等
注意一点:Redis的版本至少须要2.6,固然越高越好,API的兼容性比较强大。
只须要引入单个依赖就能够开始使用Lettuce:
<!-- https://mvnrepository.com/artifact/io.lettuce/lettuce-core --> <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>6.2.3.RELEASE</version> </dependency>
连接Redis
单机、哨兵、集群模式下链接Redis须要一个统一的标准去表示链接的细节信息,在Lettuce中这个统一的标准是RedisURI。案例如下:
package com.redis7.demo.Demo; import io.lettuce.core.RedisClient; import io.lettuce.core.RedisURI; import io.lettuce.core.SortArgs; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.sync.RedisCommands; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; public class LettuceDemp { public static void main(String[] args) { //使用构建器redisURI.builder RedisURI aDefault = RedisURI.Builder .redis("192.168.42.132") .withPort(6379) .withAuthentication("default", "123456") .build(); //创建连接客户端 RedisClient redisClient = RedisClient.create(aDefault); //创建客户端连接对象 StatefulRedisConnection<String, String> connect = redisClient.connect(); //操作命令api RedisCommands<String, String> sync = connect.sync(); //获取所有的key List<String> list = sync.keys("*"); for (String k : list) { System.out.println("keys:"+k); } //创建str sync.set("k12", "v12"); //获取值 String k12 = sync.get("k12"); System.out.println("k12的值:"+k12); //创建list sync.lpush("myList", "100","200","300"); //获取值 List<String> myList = sync.lrange("myList", 0, -1); for (String s : myList) { System.out.println("list-------:"+s); } //创建set sync.sadd("mySet", "v1", "v2", "v3"); Set<String> mySet = sync.smembers("mySet"); for (String s : mySet) { System.out.println("set-------:"+s); } //创建hash HashMap<String, String> map = new HashMap<>(); map.put("k20", "v20"); map.put("k21", "v21"); map.put("k22", "v22"); //添加键为myHash 值为map sync.hmset("myHash", map); //查看值 Map<String, String> myHash = sync.hgetall("myHash"); for (String k : myHash.keySet()) { System.out.println("hash :"+myHash.get(k)); } //创建zet sync.zadd("myZset",100.0,"s1",110.0,"s2",90.0,"s3"); List<String> myZset = sync.zrange("myZset", 0, 10); for (String s : myZset) { System.out.println("zset-------:"+s); } //sort SortArgs sortArgs = new SortArgs(); sortArgs.alpha(); sortArgs.desc(); List<String> myList1 = sync.sort("myList", sortArgs); for (String s : myList1) { System.out.println("sort ----------:"+s); } //关闭 connect.close(); redisClient.shutdown(); } }
三、RedisTemplate
RedisTemplate是Redis模块的中心类,它为与Redis的交互提供了一个高级抽象。RedisConnection提供低级方法,接收和返回二进制数组,RedisTemplate则负责序列化和连接管理,使用户不用处理这些细节。官方文档中,RedisTemplate定义为:performs automatic serialization/deserialization between the given objects and the underlying binary data in the Redis Store。
RedisTemplate一旦配置好,就是线程安全的,可供多个实例重用。
RedisTemplate的大多数操作都使用基于Java的序列化程序。这意味着它读写的任何对象都通过Java进行序列化和反序列化。你可以更改序列化机制(org.springframework.data.redis.serializer中提供了几种实现)。RedisCache和RedisTemplate默认的情况下使用JdkSerializationRedisSerializer。对于JSON格式的数据,可以使用Jackson2JsonRedisSerializer或者GenericJackson2JsonRedisSerialize。对于String密集型操作,可以考虑StringRedisTemplate。
启动一台redis主机,并且需要在防火墙开放其端口,否则将会连接出错,切记!!!
3.1.基础环境搭建
1).创建一个springboot项目:redis7_cloud

设置项目名称

2).在pom.xml中引入依赖
内容如下:我这里使用的springboot2.6.10,在使用2.7.9版本的时候有bug,所以建议版本保持一致
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.10</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.redis7</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>4.12</junit.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.18</lombok.version> <swagger.version>2.9.2</swagger.version> </properties> <dependencies> <!--springboot通用依赖模块--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--SpringBoot与Redis整合依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!--swagger2--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <!--通用基础配置--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3).添加配置内容
在application.properties中添加如下内容:
server.port=7777 spring.application.name=redis7_study # ========================logging===================== logging.level.root=info logging.level.com.atguigu.redis7=info logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n logging.file.name=D:/mylogs2023/redis7_study.log logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n # ========================swagger===================== spring.swagger2.enabled=true #在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常, #原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser, # 导致出错,解决办法是matching-strategy切换回之前ant_path_matcher spring.mvc.pathmatch.matching-strategy=ant_path_matcher # ========================redis单机===================== spring.redis.database=0 # 修改为自己真实IP spring.redis.host=192.168.42.132 spring.redis.port=6379 spring.redis.password=123456 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
4).创建config层
创建 config.SwaggerConfig 类,进行swagger的配置:
package com.redis7.demo.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @Configuration @EnableSwagger2 //开启swagger功能 public class SwaggerConfig{ @Value("${spring.swagger2.enabled}") private Boolean enabled; @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .enable(enabled) .select() .apis(RequestHandlerSelectors.basePackage("com.redis7.demo")) //你自己的package .paths(PathSelectors.any()) .build(); } public ApiInfo apiInfo() { return new ApiInfoBuilder() .title("springboot利用swagger2构建api接口文档 "+"\t"+ DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDateTime.now())) .description("springboot项目整合") .version("1.0") .termsOfServiceUrl("https://www.augus.com/") .build(); } }
5).创建service层
创建 service.OrderService 类代码如下:
package com.redis7.demo.service; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; @Service @Slf4j public class OrderService { public static final String ORDER_NUMBER = "order"; @Resource private RedisTemplate redisTemplate; //创建订单 public void CreateOrder(){ //模拟订单id int keyId = ThreadLocalRandom.current().nextInt(1000) + 1; //模拟订单编号 String orderId = UUID.randomUUID().toString(); redisTemplate.opsForValue().set(ORDER_NUMBER+keyId,"订单:"+orderId); log.info("=============>编号"+keyId+"的订单流水号:{}",orderId); } //根据id查询 public String getOrderById(Integer id){ return (String) redisTemplate.opsForValue().get(ORDER_NUMBER+id); } }
6).创建controller层
创建 controller.OrderController 类代码如下:
package com.redis7.demo.controller; import com.redis7.demo.service.OrderService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @Api(tags = "订单接口") @RestController @Slf4j public class OrderController { @Resource private OrderService orderService; @ApiOperation("新增订单") @PostMapping(value = "/oreder/add") public void createOrder() { orderService.CreateOrder(); } @ApiOperation("根据Id查询订单") @GetMapping(value = "/oreder/{id}") public String getOrderById(@PathVariable Integer id){ return orderService.getOrderById(id); } }
7).测试
启动项目,浏览器访问:http://localhost:7777/swagger-ui.html#/,如下出现swagger的的接口:

现在执行创建订单流水的接口

这时候查看结果:

3.2.序列化问题处理
出现上节的问题主要是因为 RedisTemplate,序列化对应的是defaultSerializer,默认采用的是JDK 序列化方式
1).方式一:使用 StringRedisTemplate的子类
在service层之前使用的是RedisTemplate,现在可以采用 StringRedisTemplate 子类,StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。如下:

所以如上所示,只需要将service层的代码修改如下(将RedisTemplate替换为StringRedisTemplate ):
package com.redis7.demo.service; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; @Service @Slf4j public class OrderService { public static final String ORDER_NUMBER = "order"; // @Resource // private RedisTemplate redisTemplate; @Resource private StringRedisTemplate stringRedisTemplate; //创建订单 public void CreateOrder(){ //模拟订单id int keyId = ThreadLocalRandom.current().nextInt(1000) + 1; //模拟订单编号 String orderId = UUID.randomUUID().toString(); stringRedisTemplate.opsForValue().set(ORDER_NUMBER+keyId,"订单:"+orderId); log.info("=============>编号"+keyId+"的订单流水号:{}",orderId); } //根据id查询 public String getOrderById(Integer id){ return stringRedisTemplate.opsForValue().get(ORDER_NUMBER+id); } }
重新启动项目,然后再次通过swagger发出接口请求

查看创建的数据:

会发现key虽然不乱码了,但是在客户端查看key对应的值依然乱码,这个只是客户端显示的问题,只需要在登录的时候添加上 参数:--raw
redis-cli -a 123456 --raw
如下图所示,再次查看不在乱码:

2).方式二:修改 RedisTemplate的序列化策略
RedisTemplate,序列化对应的是defaultSerializer,默认采用的是JDK 序列化方式,所有只需要修改其序列表策略即可,
在config下创建 RedisConfig 配置类,代码如下,替换掉序列化方式即可
package com.redis7.demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { /** * redis序列化的工具配置类,下面这个请一定开启配置 * 127.0.0.1:6379> keys * * 1) "ord102" 序列化过 * 2) "\xac\xed\x00\x05t\x00\aord102" 没有序列化过 * this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法 * this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法 * this.redisTemplate.opsForSet(); //提供了操作set的所有方法 * this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法 * this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法 * @param lettuceConnectionFactory * @return */ @Bean public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); //设置key序列化方式string redisTemplate.setKeySerializer(new StringRedisSerializer()); //设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化 redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } }
service层依然使用RedisTemplate,重启项目,然后执行swagger,如下:

查看生成的值

3.3.RedisTemplate和StringRedisTemplate的区别
- 两者的关系是StringRedisTemplate继承RedisTemplate。RedisTemplate是一个泛型类,而StringRedisTemplate则不是。
- 两者序列化策略不同,
- StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
- RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。
- 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
- StringRedisTemplate只能对key=String,value=String的键值对进行操作,RedisTemplate可以对任何类型的key-value键值对操作。
四、RedisTemplate操作redis集群
这里准备6台集群环境,三主三从的形式,每一台redis机器的端口都必须允许防火墙访问,否则是无法进行连接的。
4.1.修改配置文件,设置集群的配置连接
修改后application.properties文件内容如下:
server.port=7777 spring.application.name=redis7_study # ========================logging===================== logging.level.root=info logging.level.com.atguigu.redis7=info logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n logging.file.name=D:/mylogs2023/redis7_study.log logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n # ========================swagger===================== spring.swagger2.enabled=true #在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常, #原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser, # 导致出错,解决办法是matching-strategy切换回之前ant_path_matcher spring.mvc.pathmatch.matching-strategy=ant_path_matcher # ========================redis集群===================== spring.redis.password=123456 # 获取失败 最大重定向次数 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 spring.redis.cluster.nodes=192.168.42.132:6381,192.168.42.132:6382,192.168.42.134:6383,192.168.42.134:6384,192.168.42.135:6385,192.168.42.135:6386
4.2.直接通过微服务访问redis集群
在swagger中执行创建订单流水的接口:

在控制台查看生成的数据信息

同时在swagger中利用查询接口查询214这个键,对应的值:

4.3.模拟某台redis主机的宕机故障
1.模拟master-6381机器意外宕机,手动执行shutdown关闭服务,

2.先对redis集群通过命令方式,手动验证各种读写命令,看看其从机6384是否上位成为主机master

3.通过swagger再次读写访问试试
Redis Cluster集群部署采用了3主3从拓扑结构,数据读写访问master节点, slave节点负责备份。当master宕机主从切换成功,redis手动操作吗,没有问题,但是通过swagger代码执行报错:

上述问题是由于SpringBoot客户端没有动态感知到RedisCluster最新集群变化信息而导致的
4.导致原因分析
SpringBoot 2.X 版本, Redis默认的连接池采用 Lettuce当Redis 集群节点发生变化后,Letture默认是不会刷新节点拓扑,
5.如何解决上述问题
- 方案一:排除lettuce采用jedis(不推荐)

- 方案二:重写连接工厂实例(极度不推荐)
@Bean public DefaultClientResources lettuceClientResources() { return DefaultClientResources.create(); } @Bean public LettuceConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties, ClientResources clientResources) { ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder() .enablePeriodicRefresh(Duration.ofSeconds(30)) //按照周期刷新拓扑 .enableAllAdaptiveRefreshTriggers() //根据事件刷新拓扑 .build(); ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder() //redis命令超时时间,超时后才会使用新的拓扑信息重新建立连接 .timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(10))) .topologyRefreshOptions(topologyRefreshOptions) .build(); LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder() .clientResources(clientResources) .clientOptions(clusterClientOptions) .build(); RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(redisProperties.getCluster().getNodes()); clusterConfig.setMaxRedirects(redisProperties.getCluster().getMaxRedirects()); clusterConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));
}
- 方案:刷新节点集群拓扑动态感应(官网推荐)
参考网址:https://github.com/lettuce-io/lettuce-core/wiki/Redis-Cluster,如下图,本质是就是设置每隔一段时间去刷新一下集群的拓扑:

6.如何解决上述问题
采用方案三:刷新节点集群拓扑动态感应,的方式解决,修改application.properties文件内容,在redis集群下面添加内容:
# ========================redis集群===================== spring.redis.password=123456 # 获取失败 最大重定向次数 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 #支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新,默认false关闭 spring.redis.lettuce.cluster.refresh.adaptive=true #定时刷新 单位是毫秒 spring.redis.lettuce.cluster.refresh.period=2000 spring.redis.cluster.nodes=192.168.42.132:6381,192.168.42.132:6382,192.168.42.134:6383,192.168.42.134:6384,192.168.42.135:6385,192.168.42.135:6386
7.测试
先启动6381,恢复到三主三从的效果

手动创建数据操作正常:

再次模拟6381宕机

再次在swagger中执行创建订单流水的接口,会发现执行的swagger转圈等了一下,然后控制台显示生成了数据

通过查询接口验证,也能查询出来数据:


浙公网安备 33010602011771号