找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

937

积分

0

好友

120

主题
发表于 4 天前 | 查看: 18| 回复: 0

Milvus 是一款开源的云原生向量数据库,专为海量高维向量的相似性搜索与分析设计。它的核心是解决“非结构化数据(如图片、音频、文本、视频)通过向量表征后的快速检索”问题,因此在推荐系统、图像检索、语义搜索、AIGC知识库等场景中被广泛应用。

核心特性

  • 高性能:支持十亿级向量数据的毫秒级检索,提供IVF_FLAT、HNSW、DISKANN等多种索引类型。
  • 云原生:基于微服务架构,支持Kubernetes部署,具备弹性扩缩容能力。
  • 多模态兼容:能够适配TensorFlow、PyTorch等主流深度学习框架生成的向量。
  • 灵活的数据管理:支持向量与标量字段混合存储,并提供了动态增删改查、分区和TTL等功能。
  • 多语言SDK:提供了包括Python、Java、Go、Node.js、C++在内的多种编程语言客户端。
  • 高可用:通过副本与分布式部署机制,保障数据安全与服务的连续性。

核心概念

概念 说明
向量(Vector) 非结构化数据经过嵌入模型(Embedding)处理后得到的高维数值数组(例如768维)。
集合(Collection) 类似于关系型数据库中的“表”,用于存储向量及相关的标量字段。
分区(Partition) 集合的子划分,可根据时间、业务场景等维度隔离数据,以提升检索效率。
索引(Index) 为向量字段建立的加速检索结构。若未建立索引,检索将退化为性能低下的暴力(brute-force)搜索。
别名(Alias) 集合的别名,可用于在不中断业务的情况下平滑切换集合版本。
一致性级别 支持强一致性、会话一致性和最终一致性,以满足不同业务场景对数据一致性的要求。

安装部署

Milvus支持两种主流部署方式:Docker Compose(适用于单机或测试环境)Kubernetes(适用于生产环境)

前置条件

  • Docker Compose部署:需要Docker 20.10.0+和Docker Compose 2.0+。
  • Kubernetes部署:需要K8s 1.21+和Helm 3.0+。
  • 硬件建议:推荐CPU 4核以上、内存16GB以上(大规模向量数据需要更高配置),磁盘建议使用SSD。

Docker Compose部署

这是最快速的单机启动方式,适合开发和测试。

步骤1:下载配置文件

下载官方main分支的独立部署模板:

wget https://raw.githubusercontent.com/milvus-io/milvus/master/deployments/docker/standalone/docker-compose.yml -O docker-compose.yml

注意:上述链接指向最新开发版。如需固定版本(例如v2.4.6),需手动编辑docker-compose.yml文件,将milvusdb/milvus:latest替换为milvusdb/milvus:v2.4.6

步骤2:启动与验证

配置文件准备就绪后,执行以下命令启动所有服务:

# 在后台启动所有容器
docker compose up -d

# 查看所有容器的运行状态
docker compose ps

当所有容器(包括etcd、minio、standalone)的状态都显示为Up时,表示Milvus服务已成功启动。

Go SDK与版本兼容性

Milvus遵循主版本.次版本.补丁版本(例如v2.4.6)的语义化版本规则,Go SDK与服务端的兼容性至关重要。

版本类型 兼容性说明 示例
主版本(如 2.x) 主版本不同则完全不兼容。 v1.1.x SDK 无法连接 v2.4.x 服务端。
次版本(如 2.4.x) 向前兼容:高版本SDK可连接低版本服务端(但新功能可能不可用)。反向不保证:低版本SDK连接高版本服务端可能导致错误。 v2.4.x SDK 连接 v2.3.x 服务端基本可用。
补丁版本(如 2.4.6) 完全兼容,仅包含Bug修复,无接口变更。 v2.4.6 SDK 与 v2.4.3 服务端可互通。

核心原则

  • 生产环境:必须确保 SDK次版本 ≤ 服务端次版本,且补丁版本尽量接近(例如服务端为v2.4.6,SDK应使用v2.4.6或v2.4.5)。
  • 绝对禁止:使用低版本SDK连接高版本服务端(如v2.3.x SDK连接v2.4.x服务端),极易引发“未定义字段”、“协议解析失败”等错误。

如何保证版本兼容?

  1. 确认服务端版本
    # 查看Docker部署的Milvus版本
    docker inspect milvus-standalone | grep "IMAGE"
    # 输出示例:... "milvusdb/milvus:v2.4.6" ...

    也可以通过Go SDK的GetVersion方法动态获取。

  2. 安装对应版本的SDK
    # 在Go项目中,严格指定与服务端一致的版本
    go get github.com/milvus-io/milvus-sdk-go/v2@v2.4.6

完整示例代码

以下是一个使用Go SDK操作Milvus的完整示例,涵盖了连接、集合管理、数据插入、索引创建、向量检索和标量查询等核心操作。

package main

import (
    "context"
    "fmt"
    "log"
    "math/rand"
    "time"

    "github.com/milvus-io/milvus-sdk-go/v2/client"
    "github.com/milvus-io/milvus-sdk-go/v2/entity"
    "github.com/milvus-io/milvus-sdk-go/v2/grpc/client/param"
)

// generateRandomVector 生成指定维度的随机向量(模拟Embedding模型输出)
func generateRandomVector(dim int) []float32 {
    vec := make([]float32, dim)
    for i := 0; i < dim; i++ {
        vec[i] = rand.Float32() // 生成 0~1 之间的随机数
    }
    return vec
}

func main() {
    // 1. 配置连接参数
    ctx := context.Background()
    addr := "localhost:19530" // Milvus单机版默认地址
    clientParams := []param.ConnectParam{
        param.WithAddress(addr),
        param.WithConnectTimeout(5 * time.Second),
        // 生产环境若开启认证,可添加: param.WithAuthorization("root:Milvus")
    }

    // 2. 建立连接
    milvusClient, err := client.NewGrpcClient(ctx, clientParams...)
    if err != nil {
        log.Fatalf("连接 Milvus 失败: %v", err)
    }
    defer milvusClient.Close()
    fmt.Println("✅ Milvus 连接成功")

    // 3. 定义集合参数
    collectionName := "go_demo_collection"
    dim := 768                           // 向量维度(适配常见BERT等模型)
    indexType := entity.IndexTypeHNSW    // 索引类型,HNSW适用于高性能检索
    metricType := entity.MetricTypeL2    // 距离度量方式:L2欧氏距离

    // 4. 清理旧集合(演示用)
    exists, err := milvusClient.HasCollection(ctx, collectionName)
    if err != nil {
        log.Fatalf("检查集合失败: %v", err)
    }
    if exists {
        err = milvusClient.DropCollection(ctx, collectionName)
        if err != nil {
            log.Fatalf("删除集合失败: %v", err)
        }
        fmt.Printf("🗑️  已删除旧集合: %s\n", collectionName)
    }

    // 5. 创建集合(定义Schema)
    fields := []*entity.Field{
        // 主键字段 (INT64, 自增)
        {
            Name:       "id",
            DataType:   entity.FieldTypeInt64,
            PrimaryKey: true,
            AutoID:     true,
        },
        // 向量字段 (FLOAT_VECTOR, 768维)
        {
            Name:     "image_vector",
            DataType: entity.FieldTypeFloatVector,
            TypeParams: map[string]string{
                entity.TypeParamDim: fmt.Sprintf("%d", dim),
            },
        },
        // 标量字段 (VARCHAR, 存储图片名)
        {
            Name:       "image_name",
            DataType:   entity.FieldTypeVarChar,
            TypeParams: map[string]string{entity.TypeParamMaxLength: "255"},
        },
    }
    schema := &entity.Schema{
        CollectionName: collectionName,
        Fields:         fields,
        Description:    "Go SDK 演示:图片向量集合",
    }
    err = milvusClient.CreateCollection(ctx, schema, 1) // 1个分片
    if err != nil {
        log.Fatalf("创建集合失败: %v", err)
    }
    fmt.Printf("✅ 创建集合成功: %s\n", collectionName)

    // 6. 插入测试数据
    rand.Seed(time.Now().UnixNano())
    numRows := 10
    vectors := make([][]float32, 0, numRows)
    imageNames := make([]string, 0, numRows)
    for i := 0; i < numRows; i++ {
        vectors = append(vectors, generateRandomVector(dim))
        imageNames = append(imageNames, fmt.Sprintf("image_%d.jpg", i+1))
    }
    insertData := entity.NewInsertParam(collectionName)
    insertData.AddColumn("image_vector", vectors)
    insertData.AddColumn("image_name", imageNames)
    insertIDs, err := milvusClient.Insert(ctx, insertData)
    if err != nil {
        log.Fatalf("插入数据失败: %v", err)
    }
    fmt.Printf("✅ 插入 %d 条数据,生成的主键 ID: %v\n", numRows, insertIDs)

    // 7. 创建索引(检索前必需步骤)
    indexParam := &entity.IndexParam{
        CollectionName: collectionName,
        FieldName:      "image_vector",
        IndexType:      indexType,
        MetricType:     metricType,
        ExtraParams: map[string]string{
            entity.IndexParamM:              "8",  // HNSW参数:每个节点的最大连接数
            entity.IndexParamEfConstruction: "64", // 构建索引时的搜索范围
        },
    }
    err = milvusClient.CreateIndex(ctx, indexParam)
    if err != nil {
        log.Fatalf("创建索引失败: %v", err)
    }
    fmt.Println("✅ 创建索引成功")

    // 8. 加载集合到内存(检索前必需步骤)
    err = milvusClient.LoadCollection(ctx, collectionName, false)
    if err != nil {
        log.Fatalf("加载集合失败: %v", err)
    }
    fmt.Println("✅ 集合已加载到内存")

    // 9. 执行向量相似性检索 (TopK)
    queryVector := generateRandomVector(dim)
    searchParam := &entity.SearchParam{
        CollectionName: collectionName,
        FieldName:      "image_vector",
        MetricType:     metricType,
        TopK:           5, // 返回最相似的5个结果
        ExtraParams: map[string]string{
            entity.SearchParamEf: "64", // 检索时的搜索范围
        },
        OutputFields: []string{"image_name"},
    }
    searchParam.AddVectors(queryVector)
    searchResults, err := milvusClient.Search(ctx, searchParam)
    if err != nil {
        log.Fatalf("检索失败: %v", err)
    }
    fmt.Println("\n🔍 向量检索 Top5 结果:")
    for i, result := range searchResults {
        fmt.Printf("第 %d 个查询向量的结果:\n", i+1)
        for j, hit := range result {
            fmt.Printf("  排名 %d: ID=%d, 相似度得分=%.4f, 图片名称=%s\n",
                j+1, hit.ID, hit.Score, hit.Fields["image_name"])
        }
    }

    // 10. 执行标量条件查询
    queryExpr := `image_name like "image_1%"`
    queryParam := &entity.QueryParam{
        CollectionName: collectionName,
        Expr:           queryExpr,
        OutputFields:   []string{"id", "image_name"},
    }
    queryResults, err := milvusClient.Query(ctx, queryParam)
    if err != nil {
        log.Fatalf("标量查询失败: %v", err)
    }
    fmt.Printf("\n📋 标量查询结果(%s):%+v\n", queryExpr, queryResults)

    // 11. 删除数据(根据表达式)
    if len(insertIDs) > 0 {
        deleteExpr := fmt.Sprintf("id = %d", insertIDs[0])
        err = milvusClient.Delete(ctx, collectionName, deleteExpr)
        if err != nil {
            log.Fatalf("删除数据失败: %v", err)
        }
        fmt.Printf("\n🗑️  已删除 ID=%d 的数据\n", insertIDs[0])
    }

    // 12. 卸载集合释放资源
    err = milvusClient.ReleaseCollection(ctx, collectionName)
    if err != nil {
        log.Fatalf("卸载集合失败: %v", err)
    }
    fmt.Println("\n✅ 集合已卸载,程序执行完成")
}

关键注意事项

  1. 版本兼容:务必确保Go SDK与Milvus服务端的版本严格匹配(特别是主版本和次版本)。可通过go list -m github.com/milvus-io/milvus-sdk-go/v2查看当前SDK版本。
  2. 性能优化
    • 批量操作:尽量使用批量插入和检索,减少网络往返开销。
    • 索引调优:根据数据规模和性能要求调整索引参数。例如,HNSW的M参数影响精度和构建速度,efConstruction影响索引质量。
    • 连接复用:在生产环境中,应创建客户端连接池并复用,避免频繁建立和关闭连接。
  3. 错误处理:示例中使用log.Fatalf简化了错误处理。在实际生产代码中,应对网络超时、服务端异常等错误进行妥善捕获,并实现重试机制。
  4. 高可用配置:对于人工智能和搜索等关键业务场景,连接客户端时可配置param.WithMaxRetries()实现自动重连。若为集群部署,应配置多个节点地址以实现负载均衡和故障转移。



上一篇:Clash for Windows配置局域网代理:解决Jenkins实例离线与插件安装问题
下一篇:华为CANN神经网络异构计算架构全面开源:拆解AI算力的“黑盒”
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 20:53 , Processed in 0.363269 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表