SpringBoot中使用Redis-Lettuce

devtools/2024/10/22 15:31:36/

SpringBoot中使用Redis-Lettuce

  • 配置pom
  • 在`application.properties`配置`Redis`参数
  • 协议参数设置
  • 序列化参数设置
  • 实现工具`Redis`操作工具类
  • 单条数据测试
  • 批量测试

SpringBoot中一般直接引用spring-boot-starter-data-redis这个starter来使用Redis,其中具体实现方式有两种方式
1、Lettuce
2、Jedis

配置pom

注意,这里我们使用lettuce,需要用到连接池信息,这里使用的是apachecommons-pool2

<?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>3.3.3</version><relativePath/></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><properties><java.version>21</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-core</artifactId><version>3.6.8</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.11.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

application.properties配置Redis参数

具体参数信息参考org.springframework.boot.autoconfigure.data.redis.RedisProperties,不同版本有些微差别

spring.application.name=demo
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.password=XXXX
spring.data.redis.clientType=LETTUCE
spring.data.redis.lettuce.pool.enabled=true
spring.data.redis.lettuce.pool.min-idle=2
spring.data.redis.lettuce.pool.max-idle=20
spring.data.redis.lettuce.pool.max-active=20
spring.data.redis.lettuce.pool.max-wait=5000

协议参数设置

这里可以设置一些个性化的参数,其中一个就是协议版本,如果使用的Redis版本低于6.0,需要使用ProtocolVersion.RESP2

@Configuration
public class CustomLettuceClientConfigurationBuilderCustomizer implements LettuceClientConfigurationBuilderCustomizer {private static final int TIMEOUT = 30;private static final SocketOptions socketOptions = SocketOptions.builder().keepAlive(SocketOptions.KeepAliveOptions.builder().enable().idle(Duration.ofSeconds(TIMEOUT)).interval(Duration.ofSeconds(TIMEOUT / 3)).count(3).build()).tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder().enable().tcpUserTimeout(Duration.ofSeconds(TIMEOUT)).build()).build();@Overridepublic void customize(LettuceClientConfiguration.LettuceClientConfigurationBuilder clientConfigurationBuilder) {// redis 6.0以前版本需要使用ProtocolVersion.RESP2clientConfigurationBuilder.clientOptions(ClientOptions.builder().socketOptions(socketOptions).protocolVersion(ProtocolVersion.RESP3).build());}
}

序列化参数设置

1、这里直接使用的StringRedisTemplate,要求全部是字符串,序列化的工作交给调用方自己处理,
2、如果要扩展RedisTemplate<K, V>,实现自己的特殊逻辑,这里就要设置key、value的序列化方式

@Configuration
public class RedisConfig {@Beanpublic StringRedisTemplate stringRedisTemplate(LettuceConnectionFactory factory) {// 验证是否可用factory.validateConnection();// 其他参数StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(factory);return template;}
}

实现工具Redis操作工具类

public interface RedisService {/*** 写入缓存** @param key      缓存key* @param value    缓存value* @param timeout  超时时间* @param timeUnit 时间单位* @return*/void set(String key, String value, long timeout, TimeUnit timeUnit);/*** 获取缓存值** @param key 缓存key* @return*/String get(String key);
}@Service
public class RedisServiceImpl implements RedisService {@Autowiredprivate StringRedisTemplate redisTemplate;@Overridepublic void set(String key, String value, long timeout, TimeUnit timeUnit) {redisTemplate.opsForValue().set(key, value, timeout, timeUnit);}@Overridepublic String get(String key) {return redisTemplate.opsForValue().get(key);}
}

单条数据测试

@SpringBootTest
public class DemoApplicationTests {@Autowiredprivate RedisService redisService;@Testpublic void testSetGet() {String key = "hello";String value = "测试数据";redisService.set(key, value, 10, TimeUnit.SECONDS);Assertions.assertEquals(value, redisService.get(key));}
}    

批量测试

这里主要测试一下连接池参数,找到一个合理配置

public class DemoApplicationTests {@Autowiredprivate RedisService redisService;@Testpublic void testPool() {this.testSetGet();ExecutorService executorService = Executors.newFixedThreadPool(10);int total = 10000;for (int i = 0; i < 10; i++) {int calcTotal = testPool(total, executorService);Assertions.assertEquals(calcTotal, total);}executorService.shutdown();executorService.close();}private int testPool(int total, ExecutorService executorService) {long start = System.currentTimeMillis();List<CompletableFuture<Integer>> list = IntStream.rangeClosed(1, total).mapToObj(it -> {return build(it, executorService);}).toList();CompletableFuture.allOf(list.toArray(CompletableFuture[]::new)).join();int calcTotal = list.stream().filter(Objects::nonNull).map(it -> {try {return it.get();} catch (Exception e) {return 0;}}).reduce(0, Integer::sum);long end = System.currentTimeMillis();System.out.println("耗时:" + (end - start) / 1000.0 + "s");return calcTotal;}private CompletableFuture<Integer> build(int it, ExecutorService executorService) {final String key = "test:hello:" + it;final String value = "value-" + it;return CompletableFuture.supplyAsync(() -> {try {redisService.set(key, value, 10, TimeUnit.SECONDS);boolean suc = value.equals(redisService.get(key));// System.out.println("build -> " + it + " -> " + Thread.currentThread().getName());if (!suc) {System.out.println("failed ->" + it);return 0;} else {return 1;}} catch (Exception e) {System.out.println("error ->" + it + ", " + e.getMessage());return 0;}}, executorService);}
} 

http://www.ppmy.cn/devtools/104651.html

相关文章

Jupyter如何使用Anaconda的虚拟环境

Anaconda的虚拟环境大家应该都知道是什么&#xff0c;我们可以建立多个虚拟环境并在对应的环境中安装不同的python三方库从而运行不同的python项目&#xff0c;那么在jupyter中如何使用Anaconda的虚拟环境呢&#xff0c;今天就为大家分享一个这样的操作教程。 请参考图文进行以…

【SpringBoot】实体多层嵌套如何判空字段?

前言 最近在公司了接了个需求&#xff1b;需要开发一个中间系统&#xff1b;进行三方联调&#xff1b;有接口开发经验的朋友都知道&#xff1b;参数校验是必备的一项操作&#xff1b;怎么优雅的校验却是个问题&#xff1b; 我翻找了网络上的一些校验方式&#xff1b;都比较参…

嵌入式全栈开发学习笔记---Linux常用库(json)

目录 入门级问题 为什么使用json? 什么是json? json-c库 json源码 安装方法 json-c API Json类型 C-API 将一个字符串转换成符合json格式的字符串(json对象) 定义一个字符串数组 定义一个json_object结构体指针 把一个字符串转换成一个json对象 将转换成json对…

基于springboot的汽车租赁管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于springboot的汽车租赁管理系统,java…

Day-01—QT项目的新建

1.选择创建的项目类型&#xff0c;可以看到&#xff0c;这里可以创建多种语言的项目&#xff0c;可以直接用QT来进行前期C 的学习。 2.创建的名字中不要包含中文&#xff0c;可以用英文就用英文&#xff0c;如果不会英文&#xff0c;就用拼音也可以&#xff0c;保存地址中也不要…

网络安全总结①

上一篇&#xff1a;网络工程面试题② 下一篇&#xff1a;网络安全总结② 信息安全 信息安全的定义 防止任何对数 据进行未授权访问的措施 &#xff0c;或者防止造成信息有意 无意泄漏、 破坏、 丢失等 问题的发生&#xff0c; 让数据处于 远离危险、 免于威胁的状 态或特性。 …

【Java EE】深入理解 Java 线程的生命周期与状态转换

多线程编程在 Java 中是实现高效并发的核心技术之一。每个线程在其生命周期内会经历多个状态&#xff0c;这些状态反映了线程在特定时间点的行为与系统资源的使用情况。了解线程的状态及其转换机制&#xff0c;对于编写健壮的并发程序尤为重要。本文将深入探讨 Java 线程的六种…

【数据结构-前缀异或和】力扣1371. 每个元音包含偶数次的最长子字符串

给你一个字符串 s &#xff0c;请你返回满足以下条件的最长子字符串的长度&#xff1a;每个元音字母&#xff0c;即 ‘a’&#xff0c;‘e’&#xff0c;‘i’&#xff0c;‘o’&#xff0c;‘u’ &#xff0c;在子字符串中都恰好出现了偶数次。 示例 1&#xff1a; 输入&…