跳到主要内容Zvec 架构深度解析:阿里开源轻量级进程内向量数据库 | 极客日志C++Node.jsAI算法
Zvec 架构深度解析:阿里开源轻量级进程内向量数据库
Zvec 是阿里巴巴开源的轻量级进程内向量数据库,基于 Proxima 引擎构建。支持稠密与稀疏向量混合搜索,提供毫秒级低延迟性能。架构采用分层设计,包含用户层、绑定层、数据库层及核心索引框架,存储层结合 RocksDB 与 MMap。支持 C++ 原生及 Python、Node.js 绑定。目前 PyPI 包尚未发布,源码构建需初始化 Git 子模块。适用于 RAG、推荐系统及边缘计算等对延迟敏感场景。
栈溢出21 浏览 Zvec 架构深度解析:阿里开源轻量级进程内向量数据库
Zvec 是阿里巴巴开源的一个轻量级、闪电般快速的进程内向量数据库。本文将深入分析 Zvec 的代码架构,揭示其核心设计理念和技术实现细节。
一、项目概览
1.1 核心特性
Zvec 基于 Alibaba 久经考验的 Proxima 向量搜索引擎构建,提供生产级的低延迟、可扩展的相似度搜索能力:
- 极致性能:毫秒级搜索数十亿级向量
- 简单易用:无需服务器配置,零依赖安装
- 混合向量支持:同时支持稠密向量(Dense)和稀疏向量(Sparse)
- 混合搜索:语义相似度 + 结构化过滤
- 随处运行:嵌入到应用进程内运行
1.2 技术栈
| 组件 | 技术 |
|---|
| 语言 | C++17 |
| 构建系统 | CMake |
| Python 绑定 | Pybind11 |
| 存储引擎 | RocksDB |
| 向量索引 | Proxima (IVF, HNSW, Flat) |
| 序列化 | Protobuf |
| 压缩 | LZ4 |
| 位图 | CRoaring |
| 距离计算 | SIMD 加速 |
1.3 目录结构
zvec/
├── src/
│ ├── include/zvec/
│ │ ├── core/
│ │ │ ├── framework/
│ │ │ └── interface/
│ │ ├── db/
│ │ └── ailego/
│ ├── binding/python/
│ └── ailego/
├── thirdparty/
├── python/
├── tests/
└── CMakeLists.txt
二、分层架构设计
2.1 整体架构图
- 用户层:Python/Node.js 提供的 API 接口
- 绑定层:Pybind11/N-API 实现 Python 到 C++ 的桥接
- 数据库层:Collection 管理 Schema、Segment、ID 映射等
- 核心索引框架:抽象的索引接口和实现
- Proxima 引擎:实际的向量搜索算法实现
- 存储层:RocksDB 处理结构化数据,MMap 处理向量索引
三、核心索引框架详解
3.1 索引类型与选择策略
Zvec 提供三种索引类型,根据数据规模自动选择最优算法:
| 索引类型 | 适用场景 | 特点 |
|---|
| Flat | 小数据集 (<10 万) | 100% 召回率,暴力搜索 |
| IVF | 中等数据集 (10 万 -1 亿) | 聚类分区,速度与精度平衡 |
| HNSW | 大数据集 (>1 亿) | 图结构,极快查询 |
核心代码实现 (src/include/zvec/core/interface/index.h):
class Index {
public:
virtual int Add(const VectorData &vector, uint32_t doc_id);
virtual int Search(const VectorData &query, SearchParams *, SearchResult *);
virtual int Train();
virtual int Open(const std::string &file_path, StorageOptions);
};
class FlatIndex : public Index {};
class IVFIndex : public Index {};
class HNSWIndex : public Index {};
3.2 IndexHolder 系统:模板化的数据管理
IndexHolder 是一个精心设计的模板系统,用于在索引构建和搜索期间管理向量数据。
三个设计维度
- 迭代模式:
OnePass*Holder:单次遍历,迭代时消耗数据(使用 std::list)
MultiPass*Holder:支持多次遍历(使用 std::vector)
RandomAccessIndexHolder:O(1) 随机访问
- 数据类型:
NumericalIndexHolder:FP16, FP32, FP64, INT8, INT16
BinaryIndexHolder:Binary32, Binary64
SparseIndexHolder:稀疏向量(indices + values)
HybridIndexHolder:稠密 + 稀疏组合
- 元素大小计算:
element_size() 返回 dimension * sizeof(type)
- 二进制向量使用
(dim + 7) / 8 * sizeof(T) 公式
内存管理策略
OnePass holders 使用 std::list<std::pair<key, vector>>:
- 元素在迭代时被消费
- 迭代器在前进时擦除元素
- 数据随处理释放内存
MultiPass holders 使用 std::vector<std::pair<key, vector>>:
- 支持多次迭代
- 迭代器仅前进
- 内存保留直到 holder 销毁
稀疏与混合向量支持
struct SparseVector {
uint32_t count;
const void* indices;
const void* values;
};
struct HybridVector {
};
设计决策表
| Holder 类型 | 容器 | 迭代特性 | 内存策略 | 适用场景 |
|---|
| OnePass | std::list | 消费数据 | 迭代后释放 | 单次遍历(索引构建) |
| MultiPass | std::vector | 保留数据 | holder 销毁时释放 | 多次遍历(搜索精炼) |
| RandomAccess | 紧凑数组 + key 向量 | 随机访问 | 紧凑布局 | O(1) 查找需求 |
模板特化模式
3.3 查询参数系统
class HnswQueryParams : public QueryParams {
int ef_;
float radius_;
bool is_linear_;
bool is_using_refiner_;
};
class IVFQueryParams : public QueryParams {
int nprobe_;
float scale_factor_;
};
四、数据库层架构
4.1 CollectionImpl 结构
class CollectionImpl : public Collection {
std::string path_;
bool destroyed_{false};
CollectionSchema::Ptr schema_;
CollectionOptions options_;
mutable std::shared_mutex schema_handle_mtx_;
std::atomic<SegmentID> segment_id_allocator_;
std::atomic<SegmentID> tmp_segment_id_allocator_;
Segment::Ptr writing_segment_;
SegmentManager::Ptr segment_manager_;
VersionManager::Ptr version_manager_;
mutable std::shared_mutex write_mtx_;
ailego::File lock_file_;
IDMap::Ptr id_map_;
DeleteStore::Ptr delete_store_;
sqlengine::SQLEngine::Ptr sql_engine_;
};
4.2 写入模式
enum class WriteMode : uint8_t {
UNDEFINED = 0,
INSERT,
UPDATE,
UPSERT,
};
4.3 分片管理策略
Writing Segment:用于写入的活动分片
- 任意时刻仅使用单个分片
- 当达到
max_doc_count_per_segment(1000 万)时自动切换
Segment Manager:管理所有非写入分片
SegmentID allocate_segment_id() {
return segment_id_allocator_.fetch_add(1);
}
4.4 并发策略
Schema 操作:std::shared_mutex schema_handle_mtx_
写入操作:std::shared_mutex write_mtx_
五、存储与持久化架构
5.1 文件组织结构
collection_root/
├── _CollectionLock
├── meta/
│ ├── schema.pb
│ ├── config.pb
│ └── version.pb
├── segments/
│ ├── segment_00001/
│ │ ├── meta.pb
│ │ ├── data/
│ │ ├── indexes/
│ │ │ ├── flat/
│ │ │ ├── ivf/
│ │ │ └── hnsw/
│ │ ├── forward/
│ │ │ └── rocksdb/
│ │ └── sql.db
│ └── ...
├── writing_segment/
├── id_map/
├── delete_store/
└── version_manager/
5.2 存储层组件
IndexStorage (src/include/zvec/core/framework/index_storage.h):
struct MemoryBlock {
enum MemoryBlockType {
MBT_MMAP = 1,
MBT_BUFFERPOOL = 2
};
const void* data;
BufferHandle buffer_handle_;
};
class IndexStorage {
virtual int open(const std::string &path, bool create) = 0;
virtual int append(const std::string &id, size_t size) = 0;
virtual Segment::Pointer get(const std::string &id) = 0;
};
- 文档索引:ID 到文档位置的映射
- 字段索引:结构化字段的倒排索引
- 元数据存储:集合配置和状态
5.3 MMap 优化
class MMapFile {
int fd_;
void* mapped_data_;
size_t size_;
int map(const std::string &path, size_t size, int prot, int flags);
int unmap();
};
- 零拷贝读取
- 操作系统级页面缓存
- 支持超大文件(超过内存)
六、Python 绑定架构
6.1 绑定模块结构
PYBIND11_MODULE(_zvec, m){
ZVecPyTyping::Initialize(m); // 类型定义
ZVecPyParams::Initialize(m); // 参数绑定
ZVecPySchemas::Initialize(m); // Schema 绑定
ZVecPyConfig::Initialize(m); // 配置绑定
ZVecPyDoc::Initialize(m); // 文档绑定
ZVecPyCollection::Initialize(m); // 集合绑定
}
6.2 错误处理机制
C++ Status → Python Exception:
void throw_if_error(const Status &status) {
switch(status.code()) {
case StatusCode::NOT_FOUND: throw py::key_error(status.message());
case StatusCode::INVALID_ARGUMENT: throw py::value_error(status.message());
default: throw std::runtime_error(status.message());
}
}
6.3 结果解包
template<typename T>
T unwrap_expected(const tl::expected<T, Status>& exp) {
if(exp.has_value()) { return exp.value(); }
throw_if_error(exp.error());
}
6.4 Python API 示例
import zvec
schema = zvec.CollectionSchema(
name="example",
vectors=zvec.VectorSchema("embedding", zvec.DataType.VECTOR_FP32, 4)
)
collection = zvec.create_and_open(path="./zvec_example", schema=schema)
collection.insert([
zvec.Doc(id="doc_1", vectors={"embedding": [0.1, 0.2, 0.3, 0.4]}),
zvec.Doc(id="doc_2", vectors={"embedding": [0.2, 0.3, 0.4, 0.1]}),
])
results = collection.query(
zvec.VectorQuery("embedding", vector=[0.4, 0.3, 0.3, 0.1]),
topk=10
)
七、性能优化技术
7.1 向量化计算
namespace math_batch {
void dot_product_simd(const float* a, const float* b, size_t n, float* result);
void l2_distance_simd(const float* a, const float* b, size_t n, float* result);
}
7.2 内存池管理
class BufferManager {
void* allocate(size_t size);
void deallocate(void* ptr);
std::vector<void*> batch_allocate(size_t size, size_t count);
};
7.3 压缩与位图
- LZ4 压缩:极致快的压缩/解压
- CRoaring 位图:高效的集合运算
- SparseHash:Google 的稀疏哈希表
八、核心依赖库分析
| 依赖 | 用途 | 原因 |
|---|
| RocksDB | 结构化数据存储 | 高性能 KV 引擎 |
| Arrow | 列式数据格式 | 零拷贝互操作性 |
| Protobuf | 元数据序列化 | 跨语言兼容 |
| LZ4 | 数据压缩 | 极快压缩/解压 |
| CRoaring | 位图索引 | 压缩集合运算 |
| SparseHash | 稀疏数据存储 | 内存高效 |
| glog | 日志记录 | Google 风格日志 |
| ANTLR | 表达式解析 | 过滤表达式 |
| googletest | 单元测试 | Google 测试框架 |
九、数据流详解
9.1 插入流程
- 写锁保护:使用
std::shared_mutex 确保写入串行化
- 自动分片:达到 1000 万文档自动创建新分片
- ID 分配:IDMap 提供 PK → DocID 映射
- 混合存储:向量数据 → VectorStorage,标量数据 → RocksDB
- 版本控制:每次写入更新版本信息
Python API ↓ Pybind11 包装器 (throw_if_error) ↓ Collection::Insert() ↓ CollectionImpl::write_impl(INSERT) ↓
1. 获取写锁 (std::shared_mutex)
2. 检查分片容量
3. 如需要切换到新分片
4. 分配文档 ID (IDMap)
5. 写入向量数据 (VectorSegment)
6. 写入标量数据 (RocksDB)
7. 更新分片元数据
8. 释放写锁 ↓
返回 WriteResults ↓ Python WriteResults 对象
9.2 查询流程
Python VectorQuery ↓ Pybind11 包装器 ↓ Collection::Query() ↓ CollectionImpl::Query() ↓
1. 解析查询参数
2. 识别相关分片
3. 查询每个分片索引 - HNSWIndex::Search() - 或 IVFIndex::Search() - 或 FlatIndex::Search()
4. 应用过滤器(如果有)
5. 合并和排序结果
6. 精炼 top-K 结果(如果配置) ↓
返回 DocPtrList ↓ Python Doc 对象列表
十、与服务器型向量数据库对比
| 特性 | Zvec (进程内) | Milvus/Pinecone (服务器) |
|---|
| 延迟 | ~1ms | ~10-100ms |
| 部署 | 嵌入式 | 独立服务 |
| 扩展性 | 单机 | 水平扩展 |
| 配置 | 无 | 必需 |
| 资源占用 | 与应用共享 | 专用 |
十一、架构亮点总结
11.1 设计优势
- 进程内设计
- 模块化架构
- 性能优化
- SIMD 向量化计算
- 内存池管理
- MMap 零拷贝 I/O
- 类型安全
- 编译时类型检查
- Schema 验证
- 明确的向量类型
11.2 技术亮点
- 混合向量搜索: 同时支持稠密和稀疏向量
- 多语言绑定: Python + Node.js,易于扩展
- 持久化设计: MMap + RocksDB 双重存储
- 分片架构: 自动分片,水平扩展
- Proxima 基因: 继承 Alibaba 生产级引擎
十二、适用场景
- RAG 应用: 文档检索 + 向量相似度
- 推荐系统: 实时物品召回
- 语义搜索: 自然语言查询
- 图像检索: 多模态向量搜索
- 边缘计算: 嵌入式设备上的向量搜索
- 实时应用: 需要极低延迟的场景
- 轻量级部署: 无法运行独立服务的环境
十三、代码位置参考
| 功能 | 文件路径 |
|---|
| 索引接口 | src/include/zvec/core/interface/index.h |
| 集合接口 | src/include/zvec/db/collection.h |
| 索引 Holder | src/include/zvec/core/framework/index_holder.h |
| 索引存储 | src/include/zvec/core/framework/index_storage.h |
| 集合实现 | src/db/collection.cc |
| Python 绑定 | src/binding/python/model/python_collection.cc |
| Schema | src/include/zvec/db/schema.h |
| 查询参数 | src/include/zvec/db/query_params.h |
十四、部署与安装说明
注意:由于 Zvec 的 PyPI 包尚未发布,实际安装需关注官方动态。
14.1 安装现状
根据 README 文档,Zvec 声称支持 Python 3.10-3.12 版本,可通过 pip install zvec 安装。但实际尝试中发现:
- PyPI 包未发布:
pip install zvec 返回 'No matching distribution found'
- 源码构建问题:尝试从源码构建时,遇到以下问题:
- 部分第三方依赖缺少 CMakeLists.txt(thirdparty/googletest、thirdparty/gflags)
- 需要 scikit-build-core 构建系统
- 构建配置较复杂
建议:关注 GitHub Releases 获取预构建包,或等待 PyPI 正式发布。
14.2 源码构建步骤
source ~/miniforge3/bin/activate py311
git clone https://github.com/alibaba/zvec.git
cd zvec
git submodule update --init --recursive
mkdir -p test_build && cd test_build
cmake -S .. -B . -DCMAKE_BUILD_PYTHON_BINDINGS=OFF
make -j4
14.3 潜在问题与解决
- PyPI 包不存在:等待官方发布或使用 GitHub Releases
- Git Submodules 未初始化:运行
git submodule update --init --recursive
- CMake 配置失败:指定完整编译器,确保子模块已初始化
- 缺少构建依赖:需要更多依赖调整,建议查看 CI/CD 配置
十五、总结
Zvec 是一个设计精良的向量数据库,其核心优势在于:
- ✅ 轻量级: 进程内运行,零依赖
- ✅ 高性能: 基于 Proxima,毫秒级搜索
- ✅ 易用性: 简单 API,快速上手
- ✅ 灵活性: 模块化设计,易于定制
- ✅ 类型安全: 模板系统保证编译时检查
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- RSA密钥对生成器
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
- Mermaid 预览与可视化编辑
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
- 随机西班牙地址生成器
随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online