1、概览 在本教程中,我们将使用 Spring AI 框架和 RAG(检索增强生成)技术构建一个 ChatBot(聊天机器人)。在 Spring AI 的加持下,我们将与 Redis Vector(向量)数据库集成,以存储和检索数据,从而增强 LLM(大型语言模型)的提示功能。一旦 LLM 接收到包含相关数据的提示,它就会有效地用自然语言生成带有最新数据的响应,以回应用户的查询。
2、RAG 是什么? LLM 是根据互联网上的大量数据集预先训练的机器学习模型。要使 LLM 在私营企业中发挥作用,我们必须根据特定组织的知识库对其进行微调。然而,微调通常是一个耗时的过程,需要大量的计算资源。此外,经过微调的 LLM 很有可能会对查询生成不相关或误导性的响应。这种行为通常被称为 LLM 幻觉(LLM Hallucinations)。
在这种情况下,RAG 是一种优秀的技术,用于限制或将 LLM 的响应置于特定上下文中。向量数据库在 RAG 架构中发挥着重要作用,为 LLM 提供上下文信息。但是,在 RAG 架构中使用矢量(向量)数据库之前,应用必须通过 ETL(提取、转换和加载)流程对其进行填充:
Reader 从不同源检索组织的知识库文档。然后,Transformer(转换器)将检索到的文档分割成小块,并使用嵌入模型对内容进行矢量化。最后,Writer 将向量或 Embedding 加载到向量数据库。向量数据库是专门的数据库,可以在多维空间中存储这些 Embedding。
在 RAG 中,如果矢量数据库定期从组织的知识库中更新,那么 LLM 就能对几乎实时的数据做出响应。
一旦矢量数据库中的数据准备就绪,应用就可以使用它来检索用户查询的上下文数据:
应用将用户查询与矢量数据库中的上下文数据相结合形成提示,最后将其发送给 LLM。LLM 在上下文数据的范围内用自然语言生成回复,并将其发送回应用。
3、使用 Spring AI 和 Redis 实现 RAG Redis Stack 提供矢量搜索服务,我们将使用 Spring AI 框架与之集成,并构建一个基于 RAG 的 ChatBot(聊天机器人)应用。此外,我们还要使用 OpenAI 的 GPT-3.
在应用中把 Redis 当成消息队列来使用已经屡见不鲜了。我想主要原因是当代应用十有八九都会用到 Redis,因此不用再引入其他消息队列系统。而且 Redis 提供了好几种实现消息队列的方法,用起来也简单。
使用 Redis 实现消息队列的几种方式 Redis 提供了多种方式来实现消息队列。
Pub/Sub 订阅发布模式,发布者把消息发布到某个 Channel,该 Channel 的所有订阅者都会收到消息。但是这种方式最大的问题是 发布出去的消息,如果没有被监听消费,或者消费过程中宕机,那么消息就会永远丢失。适合用于临时通知之类的场景,对于需要保证数据不丢失的场景不能使用这种方式。
List List 是 Redis 提供的一种数据类型,底层是链表,可以用来实现队列、栈。
Stream Stream 是一个由 Redis 5 引入的,功能完善的消息队列。想必也是 Redis 官方团队看到太多人拿 Redis 当消息队列使,于是干脆就在 Redis 上设计出一个类似于 Kafka 的消息队列。
Steam 支持消费组消费,一条消息只能被消费组中的其中一个消费者消费。支持 消息确认、支持 回溯消费 还支持把未 ACK(确认)的消息转移给其他消费者进行重新消费,在进行转移的时候还会累计消息的转移次数,当次数达到一定阈值还没消费成功,就可以放入死信队列。
这也是 Redis 种最复杂的一种数据类型。如果你真的到了需要使用 Redis Steam 作为消息队列的地步,那不如直接使用 RabbitMQ 等更加成熟且稳定的消息队列系统。
使用 List 实现可靠的消息队列 目前来说,这是用得最多的一种方式,适用于大多数简单的消息队列应用场景。List 类型有很多指令,但是作为消息队列来说用到的只有几个个:
LPUSH key element [element ...]
把元素插入到 List 的首部,如果 List 不存在,会自动创建。
BRPOPLPUSH source destination timeout
移除并且返回 List (source)尾部的最后一个元素,并且同时会把这个元素插入到另一个 List (destination)的首部。
1、概览 Testcontainers 是一个用于创建临时 Docker 容器进行单元测试的 Java 库。当我们想要避免使用实际服务器进行测试时,它非常有用。
本文将会带你了解如何在 Spring Boot 中使用 Testcontainers 测试 Redis。
2、项目设置 使用任何测试容器的首要前提是在运行测试的机器上安装 Docker。
安装好 Docker 后,就可以开始设置 Spring Boot 应用了。
在此应用中,我们将设置一个 Redis Hash、一个 Repository 和一个使用 Repository 与 Redis 交互的 Service。
2.1、依赖 添加所需的 spring-boot-starter-test 和 spring-boot-starter-data-redis 依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 接着,还要添加 Testcontainers 依赖:
<dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers</artifactId> <version>1.17.2</version> <scope>test</scope> </dependency> 2.2、配置 在 application.properties 文件中添加 Redis 连接的详细信息:
spring.redis.host=127.0.0.1 spring.redis.port=6379 3、应用设置 我们要创建一个小型应用,向 Redis 数据库读写 Product(产品)。
3.1、Entity 创建 Product 类。
在 Spring Boot 中使用 Redis 时,你一定需要过这种需求:更新某个 Redis 的 Value 值,但是不修改它的 TTL(Time To Live),也就是过期时间。
例如:使用 Redis 存储用户的 Session,过期时间为半个小时。用户的每次访问,我们都需要更新用户 Session 的 Value 值,表示用户的最后一次访问时间。但是又不能修改用户 Session 的过期时间。
有 2 种方式可以实现。
先获取过期时间,再修改 这种方式最简单,也是最容易想到。在执行修改前,先获取到这个 Key 的剩余过期时间。然后通过 SET 命令执行修改,也就是完全覆盖这个 Key / Value,同时指定剩余的过期时间。
@Autowired StringRedisTemplate stringRedisTemplate; @Test public void test() { // session key String key = "session::01"; // 先获取 key 的过期时间,单位是秒 Long expire = this.stringRedisTemplate.getExpire(key); if (expire != null && expire > 0) { // 重新设置 key,并且指定过期时间 this.
Redisson 是一个功能十分强大的 Redis Java 客户端,它提供了丰富的功能和API,支持同步和异步操作,以及 RxJava 和响应式编程模型。Redisson 提供了50多个基于 Redis 的 Java 对象和服务,包括 分布式锁、原子计数器、分布式集合(Set、Map、List、Queue) 等高级功能。它还还支持本地缓存和 RPC 调用等功能,是开发分布式应用和使用 Redis 的理想选择。
总之,Redisson 所提供的功能已经远远超出了一个 Redis 客户端的范畴,Redis 官方也 推荐使用它 作为 Java 的 Redis 客户端。
之前我们介绍过 如何在 Spring Boot 中整合、使用 Redis。我们用到了 Spring Data Redis 组件,这是由 Spring 提供的抽象,可以使用 Jedis、Lettuce 等客户端作为实现。
Redisson 官方提供了一个 redisson-spring-boot-starter 组件,它正是 Spring Data Redis 抽象的实现,也就是说,我们可以直接使用 redisson-spring-boot-starter 无缝替换 spring-boot-starter-data-redis。
本文将会带你了解如何在 Spring Boot 中通过 redisson-spring-boot-starter 整合、使用 Redisson。
整合 Redisson 添加依赖 添加 redisson-spring-boot-starter 依赖即可。
<!-- https://mvnrepository.com/artifact/org.redisson/redisson-spring-boot-starter --> <dependency> <groupId>org.
Redis 是一款开源的,使用 C 开发的高性能内存 Key/Value 数据库,支持 String、Set、Hash、List、Stream 等等数据类型。它被广泛用于缓存、消息队列、实时分析、计数器和排行榜等场景。基本上是当代应用中必不可少的软件!
Spring Boot 对 Redis 提供了开箱即用的组件:spring-boot-starter-data-redis。通过这个 starter,我们只需要几行简单的配置就可以快速地在 Spring Boot 中整合、使用 Redis。
Spring Boot 整合 Redis Maven 依赖 <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-boot-starter-data-redis 外,还添加了 commons-pool2 依赖,是因为我们需要使用到连接池。
配置属性 只需要在 application.yaml | properties 中配置如下常用的基本属性即可:
spring: data: redis: # 连接地址 host: "localhost" # 端口 port: 6379 # 数据库 database: 0 # 用户名,如果有 # username: # 密码,如果有 # password: # 连接超时 connect-timeout: 5s # 读超时 timeout: 5s # Lettuce 客户端的配置 lettuce: # 连接池配置 pool: # 最小空闲连接 min-idle: 0 # 最大空闲连接 max-idle: 8 # 最大活跃连接 max-active: 8 # 从连接池获取连接 最大超时时间,小于等于0则表示不会超时 max-wait: -1ms 注意,如果你使用的是 spring boot 2.
在 Redis 数据库中,可以通过 EXPIRE、EXPIREAT、EXPIRETIME 命令来设置 Key 的有效时间,当一个 Key 过期后会自动从数据库中删除,释放空间。
得益于于这个特性,我们可以很轻松地实现诸多类似于 “Session” 管理、数据缓存等功能。它们都有一个共同点就是,数据不会永久保存!
在有些场景中,我们可能希望在某些 Key 过期的时候获取到通知,进行一些业务处理。或者是干脆用于 “定时通知/任务” 功能,例如:下单 30 分钟后未支付,则取消订单。那么可以在用户下单的时候使用订单号作为 key 设置到 Redis 数据库中,并且设置过期时间为 30 分钟。当超时后,我们可以在 “key 过期通知” 中获取到 key 也就是订单号,判断用户是否已经支付从而是否取消订单。
注意: Redis 的 Key 过期通知功能本质上是通过 发布/订阅 功能实现的。也就是说,它不能保证通知消息的交付,当 Key 过期时如果服务器停机、重启中则该通知消息会永久丢失。
本文将会带你学习如何在 Spring Boot 应用中使用 Spring Data Redis 监听 Redis Key 过期事件。
本文所使用的软件版本:
Spring Boot:3.1.3 Redis:7.0.5 整合 Spring Data Redis 得益于 Spring Boot 对 Redis 开箱即用的支持,只需要 2 步,就可以快速地在 Spring Boot 中整合、使用 Redis。
1、简介 在本教程中,我们将学习如何在 Spring Data Redis 中配置 key 的过期时间。
2、项目设置 假设我们有一个整合了 spring data redis 的 spring boot 项目,我们打算使用 redis 来管理用户的会话(Session)。
2.1、依赖 首先,在 pom.xml 中添加以下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>3.0.4</version> </dependency> spring-boot-starter-data-redis 将传递依赖 spring-data-redis 和 lettuce-core。
2.2、Redis 配置 其次,添加 RedisTemplate 配置:
@Configuration public class RedisConfiguration { @Bean public RedisTemplate<String, Session> getRedisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Session> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } } 2.3、Model 第三,创建 Session model:
@RedisHash public class Session { @Id private String id; private Long expirationInSeconds; } 2.
在 Spring Boot 应用中使用 Spring Cache 管理缓存时,可以通过调用 @CacheEvict(allEntries=true) 注解的方法来批量删除当前缓存(cacheNames) 下的所有缓存项目。如下:
package cn.springdoc.demo.cache; import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Component; @Component public class FooCahe { // 清除 “foo” 命名空间下的所有缓存项目 @CacheEvict(cacheNames = "foo", allEntries = true) public void clear () { } } 如果你的 Spring Cache 使用的缓存实现是 Redis,那么默认情况下它会使用 KEYS [pattern] 指令来获取、删除所有匹配的缓存项目。
测试方法如下:
package cn.springdoc.demo; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import cn.springdoc.demo.cache.FooCahe; @SpringBootTest(classes = SpringdocCacheApplication.class) class SpringdocCacheApplicationTests { static final Logger logger = LoggerFactory.
1、Spring Cache 的简介 Spring Cache 是 Spring 框架提供的一个缓存抽象层,用于简化应用中的缓存操作。它通过在方法执行期间将结果存储在缓存中,以便在相同的输入参数下,下一次调用时可以直接从缓存中获取结果,而不必执行相同的计算或查询操作。Spring Cache 支持多种缓存提供商,如 Ehcache、Redis、Caffeine 等,可以根据需求选择合适的缓存实现。通过使用 Spring Cache,开发人员可以轻松地添加缓存功能,提高应用的性能和响应速度。
Redis 是 Spring Cache 中最常用的缓存实现之一,有以下几个主要原因:
高性能:Redis 是一个基于内存的数据存储系统,具有非常高的读写性能。它将数据存储在内存中,可以快速地读取和写入数据,适合作为缓存存储。 数据结构丰富:Redis 支持多种数据结构,如字符串、哈希、列表、集合和有序集合等,这些数据结构的灵活性可以满足不同场景下的缓存需求。 持久化支持:Redis 提供了持久化机制,可以将数据存储到磁盘上,以防止数据丢失。这对于缓存数据的可靠性和持久性是非常重要的。 分布式支持:Redis 支持分布式部署,可以搭建多个 Redis 节点组成集群,实现数据的分片和负载均衡,提高了系统的扩展性和容错性。 生态系统丰富:Redis 有一个活跃的开源社区,提供了许多与 Spring 集成的库和工具,如 Spring Data Redis、Lettuce 和 Redisson 等,这些工具可以方便地与 Spring Cache 集成,简化了开发和配置的过程。 综上所述,Redis 在性能、数据结构、持久化、分布式支持以及生态系统方面的优势,使其成为 Spring Cache 中最常用的缓存实现之一。
本文将会指导你如何在 Spring Boot 中整合 Spring Cache 和 Redis 来开发缓存应用,并且修改其序列化方式为 JSON。
本文中使用的软件版本:
spring boot:3.1.3 redis:7.0.5 2、整合 Spring Cache 你可以点击 start.springboot.io 快速地创建此演示项目。
项目的依赖如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!