微信扫码
添加专属顾问
我要投稿
深入解读Milvus核心参数配置,快速提升系统性能与稳定性。核心内容:1. Milvus配置参数概览及重要性2. Milvus依赖组件(etcd、minio)配置要点3. Milvus自身组件及其他功能配置详解
最近在社区里经常听到一些小伙伴说,Milvus 的配置参数有几百个,这些参数究竟该怎么配置,Milvus 才能获得最佳的性能和稳定性。打开 Milvus 的配置文件 milvus.yaml,各个功能模块,从基础设施(存储、消息队列)到业务功能(查询、写入、索引),总共参数加起来超过了 500 多个,对于刚接触 Milvus 的朋友来说,确实无从下手。
其实 Milvus 的配置参数虽然很多,但是大部分的参数,我们平时基本都不需要关注,只需要深入理解其中的一些核心配置参数,就可以把 Milvus 运维得很好了。今天我们就从 milvus.yaml 入手,按照配置文件中的章节顺序,带大家一起来解读 Milvus 的核心配置参数及调优方案。
Milvus 的配置参数大体可以分为三大类:
Milvus 依赖组件配置:包括 Milvus 依赖的三大外部组件,etcd、minio、mq 的相关配置。
Milvus 自身组件配置:包括 proxy、rootcoord、querycoord、querynode、indexnode、datacoord、datanode 的相关配置。
其他功能配置:包括 log、security、quotaAndLimits 等 Milvus 自身功能的一些配置。
第一个依赖是 etcd, 这部分重点需要关注的配置有三个:
etcd.endpoints:这是 etcd 服务地址的配置参数,Milvus 默认会使用自己启动 etcd 服务,不过在一些大型企业中通常会有专门运维 etcd 的团队,对接他们的 etcd 服务,稳定性会更高。 修改这个参数就可以对接企业自己的etcd服务。
etcd.rootPath:存储 Milvus 元数据的 key 的前缀名,默认不需要修改。但是当我们有多套 Milvus 集群想要使用同一套 etcd 服务的时候,就可以修改不同的前缀名,来做集群元数据隔离。
etcd.auth:milvus 默认不会开启 etcd 的身份验证,但是当外部 etcd 服务开启安全验证时,可以在这里配置用户名密码。
第二个依赖是 minio,虽然这个模块的名字是"minio",但是在 Milvus 中,它其实指代的是所有的 OSS(Object Storage Service) client。
换言之,我们总是使用 minio client 来操作所有的 OSS,可以是 S3、GCS、Aliyun OOS 或其他,通过这个模块下的 cloudProvider 参数配置 OSS 提供商。这块需要关注的重点配置有四个:
minio.address/minio.port:minio 服务的配置地址,如果我们想使用第三方的 minio 服务,在此处配置服务地址。
minio.bucketName:minio 的 bucket 名字,如果有多套 Milvus 集群想要使用同一个 minio 服务时,可以通过 bucketName 来隔离。
minio.rootPath:Milvus 在 minio 里存储数据的 key 的前缀。如果有多套 Milvus 集群想要使用同一个 minio 服务的同一个 bucket 时,那么可以用 rootPath 来做隔离。
minio.cloudProvider:OSS 提供商的配置参数,常见的 OSS 提供商比如,AWS 、GCP、Aliyun 都是支持的,详见:https://milvus.io/docs/product_faq.md#Where-does-Milvus-store-data。
最后一个依赖是消息队列 mq,也有三个配置值得重点关注:
pulsar.address/pulsar.port:pulsar 的服务地址,通过这两个参数可以配置使用外部 pulsar 服务。
pulsar.tenant:pulsar 使用的租户名,当有多套 milvus 集群想要共用一套 pulsar,可以通过不同的租户名来隔离。
msgChannel.chanNamePrefix.cluster: 如果不想使用 pulsar 的多租户来做隔离,可以通过修改 message channel 的前缀名来做隔离。
Milvus 也支持 Kafka 作为 mq,开启时需要注释掉 pulsar 的相关配置,然后关闭 Kafka 配置的注释。
Milvus 第一个自身组件是 rootcoord,主要用来处理 DDL(data definition language )、DCL(data control language) 请求以及时间戳服务 TSO 的管理。这个组件需要关注如下几个配置:
rootCoord.maxPartitionNum:一个集合中允许创建的最大集合数,这个配置参数提出来,不是希望大家去修改,而是记住这个限制。当你的业务中,如果租户数超过 1024,就不推荐使用 partition 来做隔离了,推荐使用 partition key 方案,租户数可以达到百万以上。
rootCoord.enableActiveStandby:Milvus 里面的 coord 节点,不能直接做横向扩展,需要开启 ActiveStandby 模式之后才可以扩展多节点来做容灾。
Proxy 是 Milvus 用来接收和验证请求以及做结果合并的组件,里面需要关注的参数有:
proxy.maxFieldNum:Milvus 的一个集合里面可以创建多个标量字段和向量字段,但是这些字段的总数不建议超过 64,字段数过多,系统的存储压力和检索压力都会比较大。
proxy.maxVectorFieldNum:在进行多向量字段搜索时,一个集合中的向量字段数不能超过 10 个,主要在一些多模态检索,多因子认证的场景会用到。
proxy.maxShardNum:Milvus在创建集合时需要设置 shard_num,shard 可以理解数据进入 Milvus 的通道。目前建议每 2 亿条数据设置一个 shard。2 亿数据以内,设置一个 shard,2-4 亿数据设置 2 个 shard,以此类推。
proxy.accessLog:Milvus 里有一个很有用的功能,就是 accessLog,默认是关闭的,如果需要可以在这里打开,可以监测 Milvus 收到请求的详细信息,包括发送用户,ip 地址,调用接口,sdk 信息等。
Querycoord 负责监控管理 querynode 的状态以及节点间的负载均衡,配置基本都是内部使用,用户不需要关注太多,所以我们就跳过 querycoord 直接到 querynode。querynode 的配置参数很多,作为用户重点关注一个参数即可:
queryNode.mmap:mmap 的开关。对于有很多标量字段的 collection,如果把数据都存放到内存,成本肯定会很高,milvus 提供的 mmap 能力,可以很好的解决这个问题。打开这个配置的缺点就是在(内存/检索数据)比过低的情况,搜索性能会急剧下降,需要根据我们自己的场景来评估。
Indexnode 没有用户侧需要关注的参数,我们直接跳过进入到 datacoord。datacoord 主要负责数据段(segment)的大小、生命周期,以及压缩管理,同时负责数据的垃圾回收。同时,之前的 indexcoord 的功能也合并进了 datacoord,所以现在的 datacoord 还负责 create index,indexnode 索引任务调度等职责。这块重点关注如下参数:
dataCoord.segment.maxSize:控制 Milvus 集群中一个数据分片(segment)的最大尺寸(in-memory index)。总体来讲,在机器内存资源允许的情况下,这个参数设置得越大,系统中的 segment 数量会越少,查询速度也会更好。社区之前有用户分享过,单个 querynode 节点 128G 内存,将 dataCoord.segment.maxSize 设置为 8G,获得的性能比 1G 的 dataCoord.segment.maxSize 有四倍左右的提升。
dataCoord.segment.diskSegmentMaxSize:控制 Milvus 集群中一个数据分片(segment)的最大尺寸(diskann index)。和 dataCoord.segment.maxSize 的配置原则相似,不过主要是针对 disk index。
dataCoord.segment.sealProportion:一个 growing segment 转成 sealed segment 的系数。dataCoord.segment.maxSize和 dataCoord.segment.sealProportion共同决定一个 segment 何时转化为 sealed 状态。按照示意图中的默认配置,当一个 segment 的大小增长为 1024*0.12=123 MB 时,就会转化为 sealed 状态。对于一些数据更新比较频繁,且希望尽快创建好索引加快搜索性能的场景,这个参数可以设置小一点,比如 0.12,让 segment 尽快 seal 然后创建索引。对于一些偏离线场景,对性能要求不高,这个参数可以设置大一些,比如 0.3~0.5,节省索引节点的开销。
dataCoord.segment.expansionRate:compaction 过程中,segment 允许的膨胀倍数,Milvus 允许存在的最大 Segment Size = maxSize * expansionRate。
dataCoord.gc.dropTolerance:segment compaction 产生新的 segment, 老的segment 就会被清理;另外drop collection 之后,这个 collection 里的 segment 也会被清理。但是 Milvus 不会立即删除这些待清理的 segment 释放存储,而是会等 gc 时间到了之后才会物理清除。而 dataCoord.gc.dropTolerance 就是控制 gc 等待的时间。
Datanode 是负责数据写入落盘的节点,相关的配置使用默认的参数即可,这里就不展开赘述了。
Milvus 是一个组件众多的分布式系统,日志是帮助我们进行 trouble shooting 重要的工具,对于每一个用户都需要认真配置,推荐使用 Loki 这类专业的日志采集工具来收集分析 Milvus 的日志。
log.level:生产环境建议使用 info 级别日志,测试环境建议用 debug 级别。debug 级别的日志会非常多,开启 debug 等级后务必注意磁盘空间用量。
log.file:Milvus 的日志默认会打印到标准输出,同时也支持配置成文件的形式存储,对于文件的形式支持设置最大文件size,最长生命周期以及最多备份文件数。
Milvus 支持用户鉴权,以及基于角色的权限管控(RBAC),相关配置在 common 模块下:
common.security.authorizationEnabled:安全验证的控制开关,默认是关闭的。
common.security.defaultRootPassword:打开安全验证后,Milvus 默认的 root 用户密码(社区里经常问的一个问题 : )
quotaAndLimits 是 milvus.yaml 里占用篇幅很大的一块内容。Milvus 提供了非常多的限流的配置,包括写入、删除、查询等等。我们重点关注以下几个配置:
quotaAndLimits.flushRate.collection:这个参数是控制 collection 做 Flush 操作的频率,默认 0.1 是指每 10 秒只允许执行 1 次 Flush 操作。Flush 操作会做两件事,将 growing segment 转化为 sealed segment,然后将 mq 里的数据落盘到对象存储上。如果过于频繁地调用 Flush,系统会产生大量的小 segment,给系统造成较大的 compaction 压力,进而影响查询性能。Flush 一般是在插入完一批数据,不再继续插入的时候,可以手动调用一次,加快数据落盘和索引建立。在 Milvus 内部,growing segment size 达到 maxSize * sealProportion,便会自动 seal,同时系统也会每 10 分钟自动做 seal segment 的落盘,所以大部分情况下,我们不需要去手动调用 Flush。最后还需要强调一点,数据的可见性和 Flush 没关系,是由查询的一致性等级来决定的,之前社区里有不少朋友担心数据可见性的问题,每插入一次数据,都会调一次 Flush,导致系统整体性能非常差,并且影响稳定性。
quotaAndLimits.upsertRate/quotaAndLimits.deleteRate:这两个参数是用来控制 upsert 和 delete 的速率。Milvus 采用 LSM Tree 作为其底层数据结构,更新和删除操作过于频繁,会给系统的 compaction 任务产生压力。upsert 和 delete 的速率建议都不要超过 0.5MB/s。如果确实需要快速地更新一个集合中的大部分数据,建议通过 collection alias 的方式,将新数据写入新集合,更新完毕后,将 alias 指向新集合。
通过前面的梳理,大家应该对 Milvus 里的核心配置参数有了一定了解,接下来我们再通过两个常见场景,告诉大家如何灵活配置使用这些参数。
Case 1:Performance First
对于性能要求比较高的场景,比如推荐系统,金融风控,大家一般都会选择图索引,Milvus 支持的常见图索引:HNSW,DISKANN。除了索引选择外,一般会同时配合调节如下参数:
调高 dataCoord.segment.maxSize, dataCoord.segment.diskSegmentMaxSize。根据机器配置情况,可以将这两个参数调大到 4G 或者 8G。调高 maxSize 要求更高的 IndexNode 和 QueryNode 的运行时内存,且引入更多的写放大,所以务必使用较大规格的机器。
调低 dataCoord.segment.sealProportion,dataCoord.segment.expansionRate,将单个 Growing Segment maxSize 控制在 200MB 左右,减轻 Delegator (QueryNode 中的 leader 节点)的内存压力。
Case 2:Cost First
对于性能要求不严苛,但是成本比较敏感的场景,比如自动驾驶模型训练中的 corner case 图片搜索,超大规模知识库系统,我们可以利用索引量化或磁盘+内存的方式,在有限内存里装更多的数据,当然这样做的代价就是牺牲召回率或性能。索引的量化包括 SCANN,IVF_SQ8,以及 Milvus 2.5 推出的 HNSW_SQ/PQ/PRQ 索引;而使用磁盘的方式,一是可以使用磁盘索引,创建 Index 的时候选择 DISKANN 类型。第二种则是在配置文件中开启 mmap:
如果对于成本非常敏感,对于性能没有要求,推荐将 vectorField、vectorIndex、scalarField、scalarIndex 的 mmap 开关都打开。如果查询过程中需要用到标量字段且希望标量过滤性能足够快,可以将 vectorIndex、scalarIndex 的 mmap 开关关掉,来加速标量搜索的性能。需要注意的是,配合 mmap 使用的常见索引是 HNSW,这个索引会比原始数据膨胀 1.8 倍左右。所以当挂载了 100G 的磁盘,实际能装的数据只有 50G 左右,如果将原始数据也缓存到磁盘上,那么实际能装的数据就会更少,需要提前规划好磁盘空间。
对于刚开始接触 Milvus 的朋友,把上面的这些参数理解清楚并进行正确配置,基本可以解决 80% 的配置使用问题。等对 Milvus 有了一定的使用经验和理解之后,推荐大家再次打开 milvus.yaml,对里面其他的配置参数,结合注释和源码去做更加深入地学习,相信又会有很多新的体悟。
作者介绍
李成龙
Zilliz 资深开源布道师
推荐阅读
官宣|如何找到精度与性能的黄金点,Zilliz推出调优高级参数
官宣|如何找到精度与性能的黄金点,Zilliz推出调优高级参数
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-07-17
2025-01-02
2024-08-13
2025-01-03
2024-07-11
2024-08-27
2024-06-24
2024-07-13
2024-07-12
2024-06-10
2025-04-20
2025-04-15
2025-04-09
2025-03-29
2025-02-13
2025-01-14
2025-01-10
2025-01-06