SpringAI完整学习指南-涉及Redis相关问题(二)

目录

[一、排查本地 Redis 是否支持 RediSearch / RedisStack](#一、排查本地 Redis 是否支持 RediSearch / RedisStack)

[方法 1:MODULE LIST(最权威)](#方法 1:MODULE LIST(最权威))

[方法 2:直接发 FT 命令](#方法 2:直接发 FT 命令)

[方法 3:Docker 场景快速自查](#方法 3:Docker 场景快速自查)

[二、常见问题:'org.springframework.ai.vectorstore.VectorStore' that could not be found](#二、常见问题:'org.springframework.ai.vectorstore.VectorStore' that could not be found)

[三、Lettuce 和 Jedis 对比](#三、Lettuce 和 Jedis 对比)

[四、为什么 Spring AI 的 RedisVectorStore 强依赖 Jedis?](#四、为什么 Spring AI 的 RedisVectorStore 强依赖 Jedis?)

[五、常见问题:redis.clients.jedis.exceptions.JedisDataException: ERR unknown command `FT._LIST`, with args beginning with:](#五、常见问题:redis.clients.jedis.exceptions.JedisDataException: ERR unknown command FT._LIST, with args beginning with:)


一、排查本地 Redis 是否支持 RediSearch / RedisStack

方法 1:MODULE LIST(最权威)

java 复制代码
redis-cli MODULE LIST
java 复制代码
支持 RedisStack 的实例会返回若干模块,关键是看有没有 search(RediSearch)、ReJSON、timeseries、bf、redisvector 等:

  1) 1) "name"
     2) "search"          ← RediSearch(Spring AI 必需)
     3) "ver"
     4) (integer) 20810
  2) 1) "name"
     2) "ReJSON"
     ...

只要 search 模块在列表里,Spring AI 的 RedisVectorStore 就能用。 列表为空说明你跑的是普通 Redis。

方法 2:直接发 FT 命令

java 复制代码
redis-cli FT._LIST
  • 返回空数组 (empty array) → 支持 RediSearch,只是还没建索引

  • 报错 ERR unknown command 'FT._LIST' → 不支持

方法 3:Docker 场景快速自查

如果是 Docker 启的,直接看镜像名:

java 复制代码
docker ps --format "table {{.Image}}\t{{.Names}}"

如果是 redis:7-alpine 这类精简镜像,几乎肯定不带 Stack。换成:

java 复制代码
docker run -d --name redis-stack -p 6379:6379 \ 
    redis/redis-stack-server:latest

二、常见问题:'org.springframework.ai.vectorstore.VectorStore' that could not be found

java 复制代码
Parameter 2 of method chatClient in com.study.config.ChatConfig required a bean of type
  'org.springframework.ai.vectorstore.VectorStore' that could not be found.


  Action:

  Consider defining a bean of type 'org.springframework.ai.vectorstore.VectorStore' in your configuration.

**原因:**Spring Data Redis 用了 Lettuce,但 RedisVectorStore 强依赖 Jedis

Spring Boot 中 lettuce.pool 配置 + classpath 上有 lettuce(被 spring-boot-starter-data-redis 默认带入)→ 自动装配LettuceConnectionFactory,不创建 JedisConnectionFactory。

从源码来看,RedisVectorStoreAutoConfiguration 的匹配条件包含:JedisConnectionFactory必须有 Jedis 连接工厂、EmbeddingModel必须有嵌入模型。

由于容器里只有LettureConnectionFactory,@ConditionalOnBean(JedisConnectionFactory.class) 不满足 → 自动装配跳过 →RedisVectorStore bean 不注册 → Spring 报 VectorStore bean not found。

三、Lettuce 和 Jedis 对比

维度 Lettuce 🌿 Jedis ⚔️
底层 IO Netty(异步非阻塞,NIO) 原生 Socket(同步阻塞,BIO)
线程安全 ✅ 单连接天然线程安全,多线程共享 ❌ 非线程安全,必须配连接池
连接复用 单个物理连接复用多 logical connection 每个线程占用一个物理连接
API 风格 同步 + 异步(Future)+ 响应式(Flux/Mono)三套 同步为主,API 简单直接
连接池 可选(默认不用) 必须用(JedisPool)
集群支持 好且自动刷新 slot 好,但 slot 变更需要手动处理
性能(高并发) 🥇 更优(少建连接,事件驱动) 🥈 一般(依赖连接池大小)
依赖体积 大(带 Netty) 小(几十 KB)
Spring Boot 默认 ✅ 2.x 起默认 ❌ 需手动引
Spring AI RedisVectorStore ❌ 不支持 ✅ 强依赖

Lettuce 的"共享单连接"

  • 一个连接就能扛多线程并发,因为命令在 Netty pipeline 里被序列化

  • 省掉了连接池的开销(建连是很贵的)

  • 高并发下性能稳定

Jedis 的"一连接一线程"

  • 简单粗暴,每个线程独占一个物理连接

  • 连接不够用时阻塞等待

  • API 简单,适合中小项目

java 复制代码
Lettuce(异步 + 响应式)

RedisClient client = RedisClient.create("redis://localhost");
StatefulRedisConnection<String, String> conn = client.connect();

// 同步
conn.sync().set("key", "value");

// 异步
RedisFuture<String> future = conn.async().get("key");

// 响应式(Mono/Flux)
Mono<String> mono = conn.reactive().get("key");
java 复制代码
Jedis(纯同步)

JedisPool pool = new JedisPool("localhost", 6379);
try (Jedis jedis = pool.getResource()) {     // 必须从池里拿
    jedis.set("key", "value");
    String v = jedis.get("key");
}

四、为什么 Spring AI 的 RedisVectorStore 强依赖 Jedis?

RedisVectorStore 内部直接用了 Jedis 的 UnifiedJedis.ftCreate() / ftSearch() 这类 RediSearch 专属 API:

java 复制代码
// Spring AI 源码片段
public class RedisVectorStore implements VectorStore {
    private final UnifiedJedis jedis;     // ← 直接持有 Jedis 客户端

    public void add(List<Document> documents) {
        jedis.ftAdd(indexName, ...);      // 调 RediSearch 命令
    }
}

Lettuce 虽然也支持 RediSearch 命令(通过 dispatch() 自定义命令),但 Spring AI 团队选择了 Jedis------因为 Jedis 对 RediSearch的 API 封装更完整。这是历史选择,短期内不会改。

五、常见问题:redis.clients.jedis.exceptions.JedisDataException: ERR unknown command `FT._LIST`, with args beginning with:

原因:

redis的版本以及redis不支持redisSearch导致

解决方案:

下载支持redisSearch的版本,例如:redis/redis-stack-server:latest

举例WSL环境:

bash 复制代码
**下载redis:**
docker pull redis/redis-stack-server:latest

**启动redis:**
docker run -d \
  --name redis-search \
  -p 6379:6379 \
  -v ~/redis-data:/data \
  --restart always \
  redis/redis-stack-server:latest

**验证:**

**进入redis客户端**

docker exec -it redis-search redis-cli

**查看加载模块,必须出现search**

MODULE LIST

**测试检索命令**

FT.CREATE test_idx ON HASH PREFIX 1 doc: SCHEMA title TEXT

**取镜像慢解决(国内镜像加速):**
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com",
    "https://docker.mirrors.ustc.edu.cn"
  ]
}
EOF
sudo service docker restart

**权限问题兜底(若还报 socket 权限拒绝)**
sudo usermod -aG docker $USER
newgrp docker

删除冲突的旧容器:
docker rm redis-search
如果容器正在运行,加 -f 强制删除:
docker rm -f redis-searchs

作者:筱白爱学习!!

欢迎关注转发评论点赞沟通,您的支持是筱白的动力!