用对象存储做向量搜索:OpenData Vector 的轻量路线

2026-05-15 26 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:10 分钟

向量数据库几乎是当下 AI 应用的标配——RAG 需要它,语义检索需要它,推荐系统也需要它。但一提到部署,很多人就会犹豫:Milvus 要起一套集群,Qdrant 虽然单节点也能跑,持久化还是绕不开本地磁盘或独立的存储后端。对中小团队来说,"为了几百万条向量搭一套专用存储"这笔账并不好算。

OpenData Vector 走了一条不同的路:把向量索引直接建在对象存储(S3、OSS 等)上,底层依托 SlateDB 作为嵌入式存储引擎,省掉了独立向量存储系统的运维负担。思路简单,但影响不小——下面拆开看。

为什么把向量放在对象存储上有意义

传统向量数据库的架构大致是:计算层 + 专用存储层。计算层负责索引构建和查询,存储层负责向量数据的持久化和召回。这套分工在大规模场景下很合理,但对很多实际业务来说,"专用存储层"本身就是成本大头:

  • 需要单独的磁盘规划、副本策略、备份流程
  • 存储节点扩缩容和计算节点往往不能独立进行
  • 多租户场景下,存储隔离的配置复杂度陡增

对象存储天然具备持久性、可扩展性和低成本,已经是大多数团队的基础设施。如果向量索引能直接跑在对象存储上,就等于复用已有的存储投资,砍掉一整层系统

这正是 OpenData Vector 的出发点。

核心架构:SlateDB + 对象存储

OpenData Vector 的存储底座是 SlateDB——一个基于对象存储的嵌入式 key-value 数据库(思路类似 RocksDB on S3)。SlateDB 把 LSM-Tree 的写路径搬到对象存储上:WAL 和 SST 文件直接写入 S3 兼容的 bucket,内存中只保留必要的 memtable 和 block cache。

在这个基础上,OpenData Vector 做了几件事:

  1. 向量索引结构适配对象存储的读写模式——对象存储的读是高延迟、高吞吐的,不适合随机读,但批量 scan 和范围读效率不错。索引设计需要把随机访问尽量转化为顺序访问。
  2. 写入路径优化——向量插入先攒在内存,批量 flush 到对象存储,减少小文件写入。这与 SlateDB 的 LSM compaction 策略配合。
  3. 查询路径分层——热数据在本地 cache,冷数据从对象存储拉取,查询延迟取决于 cache 命中率和索引结构的设计。

整体来看,架构非常扁平:没有独立的存储集群,没有额外的 replication 层,对象存储本身就是持久化和冗余的保障

和传统方案的定位差异

这不是要替代 Milvus 或 Qdrant 的全功能场景。定位差异很明确:

维度 传统向量数据库 OpenData Vector
存储依赖 本地磁盘 / 专用存储集群 对象存储(S3/OSS)
部署复杂度 中到高 低,单进程即可启动
写入延迟 低(本地磁盘) 中(对象存储 flush 有延迟)
查询延迟 取决于 cache 命中率,冷查询偏高
扩展方式 计算存储分别扩容 对象存储天然扩展,计算层按需加
适用规模 千万到亿级向量 百万到千万级向量

简单说:如果你的向量量级在百万级、对查询延迟容忍在百毫秒级、且已经有对象存储基础设施,OpenData Vector 的性价比会非常突出。反之,如果你需要毫秒级延迟和亿级向量,传统方案仍然更合适。

实践:用 OpenData Vector 搭一个最小向量搜索服务

以下示例基于 OpenData Vector 的公开接口风格构建。由于项目仍在早期,部分 API 可能调整,请以官方仓库最新文档为准——这里展示的是典型使用模式。

1. 准备对象存储配置

假设你有一个 MinIO(本地 S3 兼容)实例在运行:

# config.yaml — OpenData Vector 存储配置
storage:
  type: s3
  endpoint: "http://localhost:9000"
  bucket: "opendata-vector"
  access_key: "minioadmin"
  secret_key: "minioadmin"
  region: "us-east-1"

index:
  dimension: 128          # 向量维度
  metric: cosine          # 距离度量:cosine / l2 / dot
  cache_size_mb: 256      # 本地 block cache 大小
  flush_batch_size: 1000  # 内存攒多少条向量再写对象存储

2. 写入向量数据

"""向 OpenData Vector 写入向量并执行搜索的最小示例"""
import numpy as np
from opendata_vector import VectorClient  # 假设的 SDK 接口

# 连接服务(服务端读取上面的 config.yaml)
client = VectorClient(endpoint="http://localhost:8080")

# 创建 collection
client.create_collection(
    name="product_embeddings",
    dimension=128,
    metric="cosine"
)

# 批量写入向量 + 元数据
vectors = np.random.randn(5000, 128).astype(np.float32)
metadatas = [{"product_id": i, "category": f"cat_{i % 10}"} for i in range(5000)]

client.upsert(
    collection="product_embeddings",
    vectors=vectors,
    ids=list(range(5000)),
    metadatas=metadatas
)

print("写入完成,向量已攒批 flush 到对象存储")

3. 执行向量搜索

# 用一条查询向量做 top-K 搜索
query = np.random.randn(128).astype(np.float32)

results = client.search(
    collection="product_embeddings",
    vector=query,
    top_k=10,
    filter={"category": "cat_3"}  # 可选:元数据过滤
)

for hit in results:
    print(f"ID={hit.id}, score={hit.score:.4f}, meta={hit.metadata}")

4. 用 Docker 快速跑一个本地环境

# 启动 MinIO 作为本地对象存储
docker run -d --name minio \
  -p 9000:9000 -p 9001:9001 \
  -e MINIO_ROOT_USER=minioadmin \
  -e MINIO_ROOT_PASSWORD=minioadmin \
  minio/minio server /data --console-address ":9001"

# 创建 bucket
docker exec minio mc alias set local http://localhost:9000 minioadmin minioadmin
docker exec minio mc mb local/opendata-vector

# 启动 OpenData Vector 服务(假设已有官方镜像)
docker run -d --name vector-service \
  -p 8080:8080 \
  -v $(pwd)/config.yaml:/etc/opendata-vector/config.yaml \
  opendata/vector-server:latest

跑完上面几步,你就有一个完整的向量写入→存储→搜索链路,所有持久化数据落在 MinIO 的 bucket 里,没有额外的数据库进程。

冷查询延迟的应对思路

对象存储的读延迟是 OpenData Vector 最明显的短板。几个可以实践的优化方向:

  • 调大 block cache:把热向量索引段尽量留在内存,cache_size_mb 根据可用内存上调。
  • 预加载热点 collection:服务启动时对高频查询的 collection 做索引预热,把 SST 文件从对象存储拉到本地 cache。
  • 读写分离部署:写入节点单进程就够了;查询节点可以多部署几个,共享同一个对象存储 bucket,各自维护本地 cache——这比传统方案的存储副本成本低得多。
  • 索引分段策略:如果业务有明显的冷热分区(比如最近 7 天的向量查询频繁),可以在索引层面做分段,热段常驻 cache,冷段按需加载。

什么时候该选它,什么时候不该

适合选 OpenData Vector 的场景:

  • 向量量级在百万到千万,不需要毫秒级延迟
  • 已有 S3/OSS 基础设施,不想再维护一套存储系统
  • 多租户 SaaS,每个租户的向量可以隔离到不同 bucket 或 prefix
  • 成本敏感,对象存储的价格远低于专用存储集群

仍然应该用传统向量数据库的场景:

  • 实时推荐、在线广告等要求 p99 延迟 < 10ms
  • 向量量级过亿,需要分布式索引分片
  • 需要丰富的过滤、动态 schema、多模态混合检索等高级功能
  • 合规要求数据不能出机房、不能放对象存储

一句话总结:OpenData Vector 不是最快的向量数据库,但可能是运维成本最低的那个。如果你的业务能接受稍高的查询延迟、且对象存储已经在用,它值得认真评估——少维护一整套存储系统,本身就是最大的收益。


相关推荐