Spring Boot整合Redis Stack构建本地向量数据库相似性查询

Spring Boot整合Redis Stack构建本地向量数据库相似性查询

在微服务架构中,数据的高效存储与快速查询是至关重要的。Redis作为一个高性能的内存数据结构存储系统,不仅可以用作缓存、消息代理,还可以扩展为向量数据库,实现高效的相似性搜索。本文将详细介绍如何使用Spring Boot整合Redis Stack,构建本地向量数据库,并进行相似性查询。

一、Redis Stack简介

Redis Stack(也称为Redis Enterprise或Redis Cloud)是一个全面的Redis解决方案,它包括了Redis数据库、Redis搜索、Redis AI、Redis JSON等多个模块,为开发者提供了丰富的数据结构和强大的功能。其中,Redis搜索模块允许我们将Redis用作向量数据库,进行相似性搜索。

二、环境准备

在开始之前,我们需要准备以下环境:

  1. JDK:确保已安装Java Development Kit(JDK),版本建议为17或更高。
  2. Maven:用于构建和管理Java项目依赖。
  3. Docker:用于运行Redis Stack容器。
  4. Spring Boot:用于构建微服务应用。
三、Redis Stack安装与配置

我们将使用Docker来安装Redis Stack。以下是安装步骤:

  1. 拉取Redis Stack镜像

    bash 复制代码
    docker pull redis/redis-stack
  2. 运行Redis Stack容器

    bash 复制代码
    docker run -d --name redis-stack -p 6379:6379 -p 5540:5540 redis/redis-stack

    这将启动Redis Stack容器,并暴露Redis服务(端口6379)和Redis Insight管理界面(端口5540)。

  3. 访问Redis Insight

    打开浏览器,访问http://localhost:5540,即可进入Redis Insight管理界面,进行Redis数据库的可视化管理。

四、Spring Boot项目构建

接下来,我们将使用Spring Boot构建一个微服务应用,用于与Redis Stack进行交互,实现向量数据库的相似性查询。

  1. 创建Spring Boot项目

    使用Spring Initializr或Maven命令创建一个新的Spring Boot项目,并添加以下依赖:

    xml 复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <!-- 其他依赖,如Spring AI(可选) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-redis-spring-boot-starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>
    </dependencies>
  2. 配置Redis连接

    application.ymlapplication.properties文件中配置Redis连接信息:

    yaml 复制代码
    spring:
      redis:
        host: localhost
        port: 6379
        # 其他配置,如密码、连接池等(可选)
  3. 创建Redis配置类

    创建一个Redis配置类,用于配置RedisTemplate和其他必要的Bean:

    java 复制代码
    @Configuration
    public class RedisConfig {
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(redisConnectionFactory);
            template.setKeySerializer(new StringRedisSerializer());
            template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
            return template;
        }
    
        // 其他配置,如HashOperations、ValueOperations等(可选)
    }
  4. 实现向量存储与查询

    为了将文本或数据转换为向量,并使用Redis进行存储和查询,我们需要一个嵌入模型(如Word2Vec、BERT等)来生成向量。这里,我们假设已经有一个向量化工具(如vectorStore),它可以将指定的字段转换为高维向量,并存储在Redis中。

    java 复制代码
    @Service
    public class VectorService {
    
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
    
        // 存储向量到Redis
        public void storeVector(String key, double[] vector) {
            // 将向量序列化为字符串或其他可存储的格式(如JSON)
            String vectorStr = Arrays.toString(vector);
            redisTemplate.opsForValue().set(key, vectorStr);
        }
    
        // 查询与给定向量最相似的K个向量
        public List<String> similaritySearch(double[] queryVector, int k) {
            // 将查询向量转换为与存储在Redis中相同格式的字符串(可选)
            String queryVectorStr = Arrays.toString(queryVector);
    
            // 使用Redis的搜索功能进行相似性搜索(这里需要实现具体的搜索逻辑)
            // 假设有一个`vectorStore.similaritySearch`方法可以进行相似性计算
            // List<Document> results = vectorStore.similaritySearch(queryVector, k);
            // 返回结果(这里仅为示例,实际应返回相似向量的键或其他相关信息)
            // return results.stream().map(Document::getKey).collect(Collectors.toList());
    
            // 由于Redis原生不支持向量搜索,这里可以使用第三方库或自定义实现
            // 以下是一个简单的示例,使用余弦相似度进行手动计算(不推荐用于生产环境)
            Map<String, Double> similarityMap = new HashMap<>();
            redisTemplate.keys("*").forEach(redisKey -> {
                String vectorStr = (String) redisTemplate.opsForValue().get(redisKey);
                double[] storedVector = Arrays.stream(vectorStr.replaceAll("[\\[\\]\\s]", "").split(","))
                        .mapToDouble(Double::parseDouble).toArray();
                double similarity = cosineSimilarity(queryVector, storedVector);
                similarityMap.put(redisKey, similarity);
            });
    
            // 按相似度排序并返回前K个结果
            List<Map.Entry<String, Double>> sortedEntries = similarityMap.entrySet().stream()
                    .sorted((e1, e2) -> Double.compare(e2.getValue(), e1.getValue()))
                    .collect(Collectors.toList());
    
            return sortedEntries.stream().limit(k).map(Map.Entry::getKey).collect(Collectors.toList());
        }
    
        // 计算余弦相似度
        private double cosineSimilarity(double[] a, double[] b) {
            double dotProduct = 0.0;
            double normA = 0.0;
            double normB = 0.0;
            for (int i = 0; i < a.length; i++) {
                dotProduct += a[i] * b[i];
                normA += a[i] * a[i];
                normB += b[i] * b[i];
            }
            return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
        }
    }

    注意 :上述代码中的vectorStore.similaritySearch方法是一个假设的方法,Redis原生并不支持向量搜索。在实际应用中,我们可以使用Redis的搜索模块(需要安装Redis Search插件)或第三方库(如Elasticsearch、FAISS等)来实现高效的向量搜索。此外,上述代码中的余弦相似度计算是手动实现的,仅用于示例,不推荐在生产环境中使用。

  5. 创建控制器

    创建一个控制器,用于接收客户端的请求,并调用VectorService进行向量存储和查询:

    java 复制代码
    @RestController
    @RequestMapping("/vectors")
    public class VectorController {
    
        @Autowired
        private VectorService vectorService;
    
        // 存储向量
        @PostMapping("/store")
        public ResponseEntity<Void> storeVector(@RequestBody Map<String, double[]> requestBody) {
            String key = requestBody.keySet().iterator().next();
            double[] vector = requestBody.get(key);
            vectorService.storeVector(key, vector);
            return ResponseEntity.ok().build();
        }
    
        // 查询相似向量
        @GetMapping("/search")
        public ResponseEntity<List<String>> similaritySearch(@RequestParam double[] queryVector, @RequestParam int k) {
            List<String> similarKeys = vectorService.similaritySearch(queryVector, k);
            return ResponseEntity.ok(similarKeys);
        }
    }
  6. 运行应用

    使用Maven或IDE运行Spring Boot应用,然后可以通过Postman或其他HTTP客户端发送请求,进行向量存储和查询。

五、总结

通过上述步骤,我们成功使用Spring Boot整合了Redis Stack,并构建了一个本地向量数据库,实现了相似性查询。然而,需要注意的是,Redis原生并不支持向量搜索,因此在实际应用中,我们需要借助Redis的搜索模块、

相关推荐
王强你强几秒前
MySQL 高级查询:JOIN、子查询、窗口函数
数据库·mysql
草巾冒小子1 分钟前
brew 安装mysql,启动,停止,重启
数据库·mysql
用户6279947182628 分钟前
南大通用GBase 8c分布式版本gha_ctl 命令-HI参数详解
数据库
斯汤雷16 分钟前
Matlab绘图案例,设置图片大小,坐标轴比例为黄金比
数据库·人工智能·算法·matlab·信息可视化
腥臭腐朽的日子熠熠生辉21 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
SQLplusDB23 分钟前
Oracle 23ai Vector Search 系列之3 集成嵌入生成模型(Embedding Model)到数据库示例,以及常见错误
数据库·oracle·embedding
喝醉酒的小白44 分钟前
SQL Server 可用性组自动种子设定失败问题
数据库
chem41111 小时前
Conmon lisp Demo
服务器·数据库·lisp
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
m0_555762901 小时前
QT 动态布局实现(待完善)
服务器·数据库·qt