在SpringBoot中集成Redis之Lettuce

SpringBoot集成Redis与单元测试示例
文章展示了如何在SpringBoot项目中配置并使用Redis作为数据存储,引入了spring-boot-starter-data-redis和commons-pool2依赖。配置包括Redis连接参数和Lettuce连接池设置。此外,还提供了一个单元测试用例,用于存取List<Student>类型的对象到Redis并进行序列化。

SpringBoot版本

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.12</version>
    <relativePath/>
</parent>

添加依赖

<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>

配置文件

spring:
  redis:
    host: localhost
    port: 6379
    database: 0
    timeout: 10000
    
    lettuce:
      pool:
        max-active: 10
        max-wait: -1
        max-idle: 5
        min-idle: 0

单元测试示例:

package com.etoak;


import com.alibaba.fastjson.JSON;
import com.etoak.test.Student;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName: TestApp
 * @Description: 类描述
 * @author: wsdhla
 * @date: 2023/06/29 18:50
 */
@SpringBootTest
public class TestAppTests {
    @Resource
    private RedisTemplate redisTemplate;

    @Test
    public void testRedis() {
        List<Student> stuList = new ArrayList<>();
        stuList.add(new Student("name1", 100));
        stuList.add(new Student("name2", 60));

        redisTemplate.opsForValue().set("stuList", stuList);

        List<Student> stuList1 = (List<Student>) redisTemplate.opsForValue().get("stuList");

        System.out.println(JSON.toJSONString(stuList1));
    }
}

<think> 我们已经在之前的讨论中明确了使用Redis缓存来优化二次模糊搜索的策略。现在,用户希望了解如何在SpringBoot集成Redis实现高性能缓存。根据引用内容,我们可以整理出以下步骤: ### 1. 添加依赖 在`pom.xml`中添加Spring BootRedis和缓存依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> ``` ### 2. 配置Redis连接 在`application.properties`或`application.yml`中配置Redis服务器信息: ```properties spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= # 如果有密码则填写 spring.redis.database=0 # 默认使用0号数据库 # 连接池配置(可选) spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0 ``` ### 3. 启用缓存 在主启动类上添加`@EnableCaching`注解: ```java @SpringBootApplication @EnableCaching public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` ### 4. 配置RedisTemplate(可选,但建议配置序列化) 默认的`RedisTemplate`使用JdkSerializationRedisSerializer,会导致存储的key和value不易读。我们可以配置一个使用String序列化key和JSON序列化value的模板(参考引用[4]): ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // 使用String序列化key StringRedisSerializer stringSerializer = new StringRedisSerializer(); template.setKeySerializer(stringSerializer); template.setHashKeySerializer(stringSerializer); // 使用Jackson2JsonRedisSerializer序列化value Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL); jsonSerializer.setObjectMapper(om); template.setValueSerializer(jsonSerializer); template.setHashValueSerializer(jsonSerializer); template.afterPropertiesSet(); return template; } } ``` ### 5. 使用缓存注解 在服务层方法上使用缓存注解,例如: - `@Cacheable`:在方法执行前检查缓存,如果缓存存在则直接返回缓存值,否则执行方法并将结果存入缓存。 - `@CacheEvict`:清除缓存。 示例(参考引用[1]和[3]): ```java @Service public class SearchService { // 使用缓存,key为关键词,缓存名称为"searchCache" @Cacheable(value = "searchCache", key = "#keyword") public List<Item> searchItems(String keyword) { // 这里是耗时的数据库查询操作 return itemRepository.findByKeyword(keyword); } // 当数据更新时,清除该关键词的缓存 @CacheEvict(value = "searchCache", key = "#item.keyword") public void updateItem(Item item) { itemRepository.save(item); } } ``` ### 6. 手动操作缓存(可选) 如果需要更灵活地操作缓存,可以注入`RedisTemplate`或`StringRedisTemplate`(参考引用[3]和[4]): ```java @Service public class RedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } // 其他操作... } ``` ### 7. 性能优化建议 - **使用连接池**:如配置中所示,使用Lettuce连接池(Spring Boot 2.x默认使用Lettuce)可以提高连接复用率[^1]。 - **合理设置缓存过期时间**:在`@Cacheable`注解中可以使用`cacheManager`配置不同的过期时间,避免缓存数据长期不更新。 - **考虑缓存穿透和雪崩**:对于不存在的key,可以缓存空值(设置较短过期时间)防止穿透;对于大量缓存同时过期,可以设置随机的过期时间避免雪崩[^2]。 ### 8. 测试 编写测试类验证缓存是否生效: ```java @SpringBootTest public class RedisCacheTest { @Autowired private SearchService searchService; @Test public void testCache() { // 第一次查询,会执行方法并存入缓存 List<Item> firstResult = searchService.searchItems("手机"); // 第二次查询相同关键词,应直接从缓存获取,不会执行方法 List<Item> secondResult = searchService.searchItems("手机"); // 可以断点查看方法是否只执行了一次 } } ``` ### 原理说明(参考引用[5]) Redis内部使用字典(哈希表)存储键值对,通过哈希算法快速定位数据,并采用渐进式rehash保证性能。作为缓存时,所有数据存储在内存中,因此访问速度极快。 通过以上步骤,即可在Spring Boot集成Redis实现高性能缓存。 --- §§相关问题§§ 1. Spring Boot中如何配置Redis的过期时间? 2. 如何解决Redis缓存穿透问题? 3. Redis的持久化机制有哪些?如何配置? [^1]: Redis的字典使用哈希表作为底层实现,提供$O(1)$的平均时间复杂度[^5]。 [^2]: 合理使用Redis可以显著提高系统性能和可靠性[^2]。 </think> ### Spring Boot集成Redis实现高性能缓存的方法 在Spring Boot集成Redis实现高性能缓存,需要遵循以下步骤(参考引用[1][3][4][5]): --- #### 1. 添加Redis依赖 在`pom.xml`中添加Spring Data Redis依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` #### 2. 配置Redis连接 在`application.properties`中配置Redis连接信息: ```properties # Redis基本配置 spring.redis.host=localhost spring.redis.port=6379 spring.redis.password=your_password spring.redis.database=0 # 连接池配置 (参考引用[1]) spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0 ``` #### 3. 配置RedisTemplate 创建配置类自定义序列化方式(参考引用[4]): ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // Key序列化 template.setKeySerializer(new StringRedisSerializer()); // Value序列化(JSON格式) Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); template.setValueSerializer(serializer); // HashKey序列化 template.setHashKeySerializer(new StringRedisSerializer()); // HashValue序列化 template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; } } ``` #### 4. 实现缓存服务工具类 ```java @Service public class RedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; // 设置缓存(TTL单位:秒) public void set(String key, Object value, long ttl) { redisTemplate.opsForValue().set(key, value, ttl, TimeUnit.SECONDS); } // 获取缓存 public Object get(String key) { return redisTemplate.opsForValue().get(key); } // 删除缓存 public Boolean delete(String key) { return redisTemplate.delete(key); } // 检查Key是否存在 public Boolean hasKey(String key) { return redisTemplate.hasKey(key); } } ``` #### 5. 启用缓存注解 在主启动类添加注解(参考引用[1]): ```java @SpringBootApplication @EnableCaching // 启用缓存注解 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` #### 6. 在业务层使用缓存 ```java @Service public class ProductService { @Autowired private ProductRepository repository; @Autowired private RedisService redisService; // 使用注解自动缓存(参考引用[1]) @Cacheable(value = "products", key = "#id") public Product getProductById(Long id) { return repository.findById(id).orElse(null); } // 手动缓存示例 public List<Product> searchProducts(String keyword) { String cacheKey = "search:" + keyword; // 检查缓存是否存在 Object cached = redisService.get(cacheKey); if (cached != null) { return (List<Product>) cached; } // 数据库查询 List<Product> results = repository.findByKeyword(keyword); // 设置缓存(有效期10分钟) redisService.set(cacheKey, results, 600); return results; } } ``` #### 7. 性能优化技巧 1. **数据结构选择**(参考引用[5]): - 简单K-V:String类型 - 对象存储:Hash类型 - 列表操作:List类型 ```java // 使用Hash存储对象 redisTemplate.opsForHash().putAll("product:1001", product.getAttributes()); ``` 2. **批量操作减少网络IO**: ```java redisTemplate.executePipelined((RedisCallback<Object>) connection -> { for (Product p : products) { connection.set( ("product:" + p.getId()).getBytes(), serialize(p) ); } return null; }); ``` 3. **设置合理过期时间**: ```java // 随机过期时间避免缓存雪崩 int randomTTL = 600 + new Random().nextInt(300); redisTemplate.expire(key, randomTTL, TimeUnit.SECONDS); ``` 4. **使用本地二级缓存**(Caffeine + Redis): ```java @Bean public CacheManager cacheManager() { CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager(); caffeineCacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS)); return new RedisCacheManager(redisTemplate, caffeineCacheManager); } ``` #### 8. 缓存监控与管理 1. 使用`RedisHealthIndicator`监控状态 2. 集成Spring Boot Actuator: ```properties management.endpoint.health.show-details=always management.endpoints.web.exposure.include=health,info ``` 3. 使用RedisInsight等可视化工具 --- ### 性能对比 | 操作类型 | 数据库查询 | Redis缓存 | |---------|-----------|-----------| | 首次读取 | $$O(n)$$ | $$O(n) + O(1)$$ | | 重复读取 | $$O(n)$$ | $$O(1)$$ | | 吞吐量 | 100-1000 QPS | 10,000-100,000 QPS | > 说明:Redis基于内存操作,读写性能通常在微秒级($$\mu s$$),而数据库操作在毫秒级($$ms$$)[^2][^5] ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wsdhla

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值