尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Milvus Query 体系源码深度剖析:QueryCoordinator、QueryNode 接口契约与 Collection Replica 设计

Milvus Query 体系源码深度剖析:QueryCoordinator、QueryNode 接口契约与 Collection Replica 设计 Milvus Query 体系源码深度剖析QueryCoordinator、QueryNode 接口契约与 Collection Replica 设计【免费下载链接】milvusMilvus is a high-performance, cloud-native vector database built for scalable vector ANN search项目地址: https://gitcode.com/GitHub_Trending/mi/milvus本文是 Milvus 2.0 开发指南的专题续写围绕归档文档 developer_guides/chap07_query_coordinator.md 展开面向希望深入理解 Milvus 查询链路数据加载、segment 分发、查询执行、内存副本一致性的研发工程师。读完本文你将掌握 QueryCoord 与 QueryNode 的完整接口契约、查询/检索消息在 channel 中的流转方式、Collection Replica 在查询节点内部的数据组织模型并能在当前仓库源码pkg/proto/querypb、internal/querycoordv2、internal/querynodev2中一一对照印证。说明chap07 描述的是 Milvus 2.0 时代的查询架构。时至今日仓库中查询协调与执行已演进为internal/querycoordv2/与internal/querynodev2/两套实现但协调者下发任务、节点持有内存副本、消息通道驱动状态同步的核心思想一脉相承读者可借此理解架构演进的来龙去脉。1. 查询体系在 Milvus 整体架构中的定位在 chap01_system_overview.md 中Milvus 把数据组织为 collection表→ partition可选的分片逻辑单元→ segment group → segment 的层级collection/partition 是查询的基本执行范围segment group 是数据到节点映射、以及副本调度的基本单位segment 是数据与索引真正驻留的最细粒度单元其内部按列column-based布局以便利用 SIMD 降低查询内存占用。在这种模型下一套独立的查询子系统负责回答两类问题数据该被谁持有一个 collection/partition 的 segment 数据与索引分布在哪些查询节点上、何时加载、何时释放查询如何被执行用户发起的向量搜索search与按主键/标量条件取行retrieve/query如何被路由到持有数据的节点上执行并把结果收敛回 Proxy。上述第 1 类问题的大脑是Query CoordinatorQueryCoord第 2 类问题的执行体是QueryNode。文档 chap07 正是围绕这两个组件的接口契约、两者之间的消息通道以及 QueryNode 内部用于承接数据的内存副本结构Collection Replica展开的。2. QueryCoord 总览与核心职责文档 7.1 Overview 给出 QueryCoord 的系统定位它是查询侧的协调者负责元数据获取、segment 归属决策与生命周期管理是查询数据从已落盘到可被检索的关键枢纽。从仓库当前实现看这一职责被延续并进一步拆分。internal/querycoordv2/下的目录与文件如 segment 分配、collection 顶层编排、负载均衡相关的segments、dist、balancer等子包承担了 2.0 时代 QueryCoord 演进后的调度逻辑而归档文档中的 QueryCoord 更强调其对外的控制面接口与通过消息流建立的数据面通道。QueryCoord 向下要与两类基础服务打交道见上文架构图RootCoord获取 collection/partition 的 Schema 与 segment 描述图中Schema / Seg DescriptionIndexCoord获取索引描述Index Description从而得知每个 segment 是否已建好可用索引TxnKVetcd/ KVminIO/S3/内存 KV持久化查询侧的元数据、读取索引文件IndexFilesMsgStream如 Pulsar通过消息流收发DdRequest / DmRequest / DqRequest / SegInfo等控制事件与TimeTick / Stats / DqResult等状态/结果信号。3. QueryCoord 接口契约文档 7.2QueryCoord 以 gRPC 接口对外提供服务。文档给出的核心 Go 接口如下其语义直接映射到查询控制面的每一条关键路径type QueryCoord interface { Component TimeTickProvider // ShowCollections notifies RootCoord to list all collection names and other info in database at specified timestamp ShowCollections(ctx context.Context, req *querypb.ShowCollectionsRequest) (*querypb.ShowCollectionsResponse, error) // LoadCollection notifies Proxy to load a collections data LoadCollection(ctx context.Context, req *querypb.LoadCollectionRequest) (*commonpb.Status, error) // ReleaseCollection notifies Proxy to release a collections data ReleaseCollection(ctx context.Context, req *querypb.ReleaseCollectionRequest) (*commonpb.Status, error) // ShowPartitions notifies RootCoord to list all partition names and other info in the collection ShowPartitions(ctx context.Context, req *querypb.ShowPartitionsRequest) (*querypb.ShowPartitionsResponse, error) // LoadPartitions notifies Proxy to load partitions data LoadPartitions(ctx context.Context, req *querypb.LoadPartitionsRequest) (*commonpb.Status, error) // ReleasePartitions notifies Proxy to release collections data ReleasePartitions(ctx context.Context, req *querypb.ReleasePartitionsRequest) (*commonpb.Status, error) // CreateQueryChannel creates the channels for querying in QueryCoord. CreateQueryChannel(ctx context.Context) (*querypb.CreateQueryChannelResponse, error) GetPartitionStates(ctx context.Context, req *querypb.GetPartitionStatesRequest) (*querypb.GetPartitionStatesResponse, error) // GetSegmentInfo requests segment info GetSegmentInfo(ctx context.Context, req *querypb.GetSegmentInfoRequest) (*querypb.GetSegmentInfoResponse, error) // GetMetrics gets the metrics about QueryCoord. GetMetrics(ctx context.Context, req *milvuspb.GetMetricsRequest) (*milvuspb.GetMetricsResponse, error) }接口继承了Component组件生命周期与TimeTickProvider提供查询侧时间推进这是 Milvus 流式时间体系在查询协调层的落地。逐个方法看其作用ShowCollections / ShowPartitions查询当前可见的 collection/partition 及其内存化进度InMemoryPercentagesLoadCollection / LoadPartitions / ReleaseCollection / ReleasePartitions加载/释放数据是用户执行load/release的底层语义CreateQueryChannel为一个 collection 建立查询消息通道见第 4 节GetPartitionStates轮询 partition 的加载状态机GetSegmentInfo返回指定 segment 的内存驻留、行数、索引等信息供观测与调试。3.1 消息公共头 MsgBase所有请求都携带公共消息头用于在分布式与消息流环境中标识消息来源与顺序type MsgBase struct { MsgType MsgType MsgID UniqueID Timestamp Timestamp SourceID UniqueID }MsgType消息类别决定它走哪条处理分支Timestamp消息的逻辑时间戳Milvus 依赖它对何时可见做一致性判定SourceID产生方节点标识便于接收方溯源与去重。3.2 ShowCollections 与 ShowPartitionstype ShowCollectionRequest struct { Base *commonpb.MsgBase DbID UniqueID CollectionIDs []int64 } type ShowCollectionResponse struct { Status *commonpb.Status CollectionIDs []UniqueID InMemoryPercentages []int64 }注意接口注释里notifies RootCoord to list all collection names即查询协调者需要借助根协调者的元数据回答系统里有哪些 collection、各有多少比例已加载进内存。InMemoryPercentages与第 7 节的 segment/partition 状态机是一体两面百分比由 QueryCoord 依据各 partition 的 segment 加载情况汇总而来。ShowPartitions 的请求/响应结构与之对称只是把粒度下沉到 collection 内的 partitiontype ShowPartitionRequest struct { Base *commonpb.MsgBase DbID UniqueID CollectionID UniqueID PartitionIDs []int64 } type ShowPartitionResponse struct { Status *commonpb.Status PartitionIDs []UniqueID InMemoryPercentages []int64 }3.3 Load / Release集合与分区的加载生命周期加载类请求的核心载荷是要加载谁的 schema、哪些分区type LoadCollectionRequest struct { Base *commonpb.MsgBase DbID UniqueID CollectionID UniqueID schema *schemapb.CollectionSchema } type LoadPartitionRequest struct { Base *commonpb.MsgBase DbID UniqueID CollectionID UniqueID PartitionIDs []UniqueID Schema *schemapb.CollectionSchema }携带schema是因为加载动作的本质是把该集合的全部/部分 partition 的 segment 元数据与索引描述取回并调度各 QueryNode 把数据搬进内存schema 用于 QueryNode 侧反序列化与段加载。释放类请求则只需身份信息即可type ReleaseCollectionRequest struct { Base *commonpb.MsgBase DbID UniqueID CollectionID UniqueID } type ReleasePartitionRequest struct { Base *commonpb.MsgBase DbID UniqueID CollectionID UniqueID PartitionIDs []UniqueID }3.4 GetPartitionStates分区加载状态机加载不是一蹴而就的尤其在大数据量下要经历搬运 建索引 服务的多个阶段。文档定义了如下状态枚举type PartitionState int const ( PartitionState_NotExist PartitionState 0 // 分区不存在 PartitionState_NotPresent PartitionState 1 // 尚未加载未驻留内存 PartitionState_OnDisk PartitionState 2 // 数据在磁盘上如 disk 索引尚未进入内存服务 PartitionState_PartialInMemory PartitionState 3 // 部分 segment 已加载进内存 PartitionState_InMemory PartitionState 4 // 全部进入内存可服务查询 PartitionState_PartialInGPU PartitionState 5 // 部分 segment 驻留 GPU 显存 PartitionState_InGPU PartitionState 6 // 全部驻留 GPU 显存 )该枚举同样存在于当前仓库的查询协议定义中见 pkg/proto/querypb/query_coord.pb.goPartitionState_NotExist等常量——这为该设计在后续版本被继承提供了直接证据。状态值按资源层级递增从不存在/未驻留经磁盘 → 内存两段再到 GPU 加速形态。PartitionState_PartialInMemory等中间态意味着查询服务可以在分区部分加载完成时就开始提供尽力而为的服务而非全有全无。type PartitionStatesRequest struct { Base *commonpb.MsgBase DbID UniqueID CollectionID UniqueID PartitionIDs []UniqueID } type PartitionStates struct { PartitionID UniqueID State PartitionState } type PartitionStatesResponse struct { Status *commonpb.Status PartitionDescriptions []*PartitionStates }3.5 CreateQueryChannel 与 GetSegmentInfoCreateQueryChannel的返回揭示了查询消息通道的请求 / 结果二元命名模型type CreateQueryChannelResponse struct { Status *commonpb.Status RequestChannelName string ResultChannelName string }GetSegmentInfo文档以\*标注为进阶内容用于细粒度观测 segment 级状态type GetSegmentInfoRequest struct { Base *commonpb.MsgBase SegmentIDs []UniqueID } type SegmentInfo struct { SegmentID UniqueID CollectionID UniqueID PartitionID UniqueID MemSize UniqueID NumRows UniqueID IndexName string IndexID UniqueID } type GetSegmentInfoResponse struct { Status *commonpb.Status Infos []*SegmentInfo }4. Query Channel查询请求与结果的消息载体文档 7.3在 2.0 的流式架构中用户查询不是像传统 RPC 那样直连查询节点而是经过请求通道 / 结果通道两级消息流中转。CreateQueryChannel一次性返回一对通道名RequestChannelNameProxy 把用户查询打包成消息发布到该通道ResultChannelName执行查询的 QueryNode 把搜索结果发布到该通道Proxy 订阅取回。通道上流动的两类核心消息是SearchMsg与RetrieveMsg。4.1 SearchMsg向量搜索请求type SearchRequest struct { Base *commonpb.MsgBase ResultChannelID string DbID int64 CollectionID int64 PartitionIDs []int64 Dsl string PlaceholderGroup []byte DslType commonpb.DslType SerializedExprPlan []byte OutputFieldsId []int64 TravelTimestamp uint64 GuaranteeTimestamp uint64 } type SearchMsg struct { BaseMsg SearchRequest }几个关键字段说明Dsl DslType PlaceholderGroup查询 DSL 与序列化的占位符组query vectors 经 protobuf 打包DslType决定 DSL 解释方式SerializedExprPlan由 DSL 编译得到的表达式执行计划查询节点直接执行PartitionIDs限定在哪些分区内搜索OutputFieldsId需要随结果返回的标量字段TravelTimestamp时间旅行与GuaranteeTimestamp一致性保证水位是 Milvus 时间语义的两个端点查询需要看到TravelTimestamp之前的快照且要求数据服务水位至少推进到GuaranteeTimestamp。若数据还不够新查询会被挂起等待见 chap01_system_overview.md 中异步状态同步的论述。这一机制的现代版解析可参考 how-guarantee-ts-works.md。4.2 RetrieveMsg按表达式取行请求type RetrieveRequest struct { Base *commonpb.MsgBase ResultChannelID string DbID int64 CollectionID int64 PartitionIDs []int64 SerializedExprPlan []byte OutputFieldsId []int64 TravelTimestamp uint64 GuaranteeTimestamp uint64 } type RetrieveMsg struct { BaseMsg RetrieveRequest }Retrieve 与 Search 的差别在于没有向量相关字段其执行计划通常是主键/标量过滤表达式返回满足条件行的原始数据point query / filter query。两者共享同一套ResultChannelID回传模型与时间戳语义。5. QueryNode查询的执行节点接口文档 7.4如果说 QueryCoord 决定加载什么、谁来加载、何时加载QueryNode 则负责把加载任务落成内存数据、把查询消息消费成结果。文档给出的接口type QueryNode interface { Component TimeTickProvider // AddQueryChannel notifies QueryNode to subscribe a query channel and be a producer of a query result channel. AddQueryChannel(ctx context.Context, req *querypb.AddQueryChannelRequest) (*commonpb.Status, error) // RemoveQueryChannel removes the query channel for QueryNode component. RemoveQueryChannel(ctx context.Context, req *querypb.RemoveQueryChannelRequest) (*commonpb.Status, error) // WatchDmChannels watches the channels about data manipulation. WatchDmChannels(ctx context.Context, req *querypb.WatchDmChannelsRequest) (*commonpb.Status, error) // LoadSegments notifies QueryNode to load the sealed segments from storage. The load tasks are sync to this // rpc, QueryNode will return after all the sealed segments are loaded. LoadSegments(ctx context.Context, req *querypb.LoadSegmentsRequest) (*commonpb.Status, error) // ReleaseCollection notifies Proxy to release a collections data ReleaseCollection(ctx context.Context, req *querypb.ReleaseCollectionRequest) (*commonpb.Status, error) // ReleasePartitions notifies Proxy to release partitions data ReleasePartitions(ctx context.Context, req *querypb.ReleasePartitionsRequest) (*commonpb.Status, error) // ReleaseSegments releases the data of the specified segments in QueryNode. ReleaseSegments(ctx context.Context, req *querypb.ReleaseSegmentsRequest) (*commonpb.Status, error) // GetSegmentInfo requests segment info GetSegmentInfo(ctx context.Context, req *querypb.GetSegmentInfoRequest) (*querypb.GetSegmentInfoResponse, error) // GetMetrics gets the metrics about QueryNode. GetMetrics(ctx context.Context, in *milvuspb.GetMetricsRequest, opts ...grpc.CallOption) (*milvuspb.GetMetricsResponse, error) }这些方法把查询节点的工作拆成三类通道订阅类AddQueryChannel让节点订阅某 collection 的 request 通道、并成为其 result 通道的生产者RemoveQueryChannel反向注销。请求结构仅需指明节点与两侧通道type AddQueryChannelRequest struct { Base *commonpb.MsgBase NodeID int64 CollectionID int64 RequestChannelID string ResultChannelID string } type RemoveQueryChannelRequest struct { Base *commonpb.MsgBase NodeID int64 CollectionID int64 RequestChannelID string ResultChannelID string }增量数据订阅类WatchDmChannels让节点开始消费某个 vchannel数据流通道的增量写入从而把 growing 数据实时搬到查询侧type WatchDmChannelsRequest struct { Base *commonpb.MsgBase NodeID int64 CollectionID int64 PartitionID int64 Infos []*datapb.VchannelInfo Schema *schemapb.CollectionSchema ExcludeInfos []*datapb.SegmentInfo }Infos要 watch 的 vchannel 信息与ExcludeInfos需要排除的 segment通常是已转为 sealed、改走加载路径的部分的组合保证了增量订阅与存量加载之间不重不漏。存量加载/释放类LoadSegments把已封口sealed的 segment 从对象存储中拉入内存建立可查询结构。注释特别强调该 RPC 是同步语义——只有当所有指定 segment 全部加载完成后才返回这简化了 QueryCoord 对加载完成的判定type LoadSegmentsRequest struct { Base *commonpb.MsgBase NodeID int64 Infos []*SegmentLoadInfo Schema *schemapb.CollectionSchema LoadCondition TriggerCondition }ReleaseSegments / ReleasePartitions / ReleaseCollection则是释放路径支持从最细粒度segment到整体collection的逐级回收type ReleaseSegmentsRequest struct { Base *commonpb.MsgBase NodeID int64 DbID UniqueID CollectionID UniqueID PartitionIDs []UniqueID SegmentIDs []UniqueID }6. Collection Replica查询节点内的内存副本模型文档 7.5文档 7.5 是本章最硬核的部分它揭示 QueryNode 内部如何组织数据。核心概念是collectionReplica一个 collection/partition 的持久数据在查询节点内存中的本地副本。系统通常有多个查询节点一个 collection 的数据会被打散分布到所有可用查询节点上每个节点的collectionReplica只维护自己承担的那一份collection 的部分数据——这对应第 1 节segment group 是数据到节点映射的基本单元的调度语义。每个 replica 维护一个名为tSafe的水位值——replica 数据最新推进到的时间戳上限。这是查询一致性的基石当 SearchMsg/RetrieveMsg 携带的GuaranteeTimestamp ≤ tSafe时本地查询可安全执行无需等待。6.1 collectionReplica 主结构type collectionReplica struct { tSafes map[UniqueID]tSafer // map[collectionID]tSafer mu sync.RWMutex // guards all collections map[UniqueID]*Collection partitions map[UniqueID]*Partition segments map[UniqueID]*Segment excludedSegments map[UniqueID][]*datapb.SegmentInfo // map[collectionID]segmentIDs }四个 map 分别按 collectionID / partitionID / segmentID 索引三类对象构成collection → partitions → segments的自上而下持有链excludedSegments记录需要从增量订阅中剔除的 segment一把sync.RWMutex保护整体并发访问因为查询读取与 WatchDmChannels/LoadSegments 带来的结构变更会同时发生。6.2 Collection一次加载的顶层单元type FieldSchema struct { FieldID int64 Name string IsPrimaryKey bool Description string DataType DataType TypeParams []*commonpb.KeyValuePair IndexParams []*commonpb.KeyValuePair } type CollectionSchema struct { Name string Description string AutoID bool Fields []*FieldSchema }注意Collection.collectionPtr C.CCollectionschema 描述由 Go 持有而实际的可查询数据载体由 C 侧Segcore见 docs/archive/milvus-2.0/segcore 下的 segment 文档承载C.CCollection正是 Go ↔ C 的桥接指针——Milvus 的查询执行核心在 C 层以列存结构完成向量计算。type Collection struct { collectionPtr C.CCollection id UniqueID partitionIDs []UniqueID schema *schemapb.CollectionSchema vChannels []Channel pChannels []Channel loadType loadType releaseMu sync.RWMutex releasedPartitions map[UniqueID]struct{} releaseTime Timestamp }字段含义partitionIDs本节点持有该 collection 的哪些 partitionvChannels / pChannels虚拟数据通道与物理通道pChannels对应该节点消费的 DmChannel 上游vChannels是对外暴露的逻辑通道视图loadType本次加载的类型整个 collection 还是指定 partition用于释放语义的判定releasedPartitions与releaseTime记录已执行释放的分区与释放时间防止释放请求乱序到达导致的误删。6.3 Partition 与 Segment持有链的中间层与最小单元Partition 非常轻量只是把 segment 归属关系串起来type Partition struct { collectionID UniqueID partitionID UniqueID segmentIDs []UniqueID }Segment 则是结构最丰富的对象type segmentType int32 const ( segmentTypeInvalid segmentType iota segmentTypeGrowing segmentTypeSealed segmentTypeIndexing ) type indexParam map[string]string type Segment struct { segmentPtr C.CSegmentInterface segmentID UniqueID partitionID UniqueID collectionID UniqueID onService bool vChannelID Channel lastMemSize int64 lastRowCount int64 once sync.Once // guards enableIndex enableIndex bool rmMutex sync.Mutex // guards recentlyModified recentlyModified bool typeMu sync.Mutex // guards builtIndex segmentType segmentType paramMutex sync.RWMutex // guards index indexInfos map[FieldID]*indexInfo idBinlogRowSizes []int64 vectorFieldMutex sync.RWMutex // guards vectorFieldInfos vectorFieldInfos map[UniqueID]*VectorFieldInfo pkFilter *bloom.BloomFilter // bloom filter of pk inside a segment }对 Segment 结构做几点工程解读生命周期与类型segmentType在growing增量写入中→ sealed已封口→ indexing已就索引间迁移文档注释中标出的segmentTypeInvalid iota说明该常量组自 0 开始按声明顺序编号Go 的 iota 语义保证了类型值稳定且紧凑内存汇报lastMemSize / lastRowCount是节点周期性向 QueryCoord 汇报的资源快照供其做负载均衡与副本调度呼应第 1 节节点过载时把部分 segment group 迁移到低载节点索引相关enableIndex / indexInfos决定该 segment 查询走暴力扫描还是索引检索vectorFieldInfos记录向量字段的维度等元数据去重与状态追踪pkFilter是段内主键的 Bloom Filter用于WatchDmChannels场景下的主键去重判断——同一主键的重复写入需按序处理并发控制结构上散布了once / rmMutex / typeMu / paramMutex / vectorFieldMutex等多把细粒度锁各自保护独立的易变状态是否启用索引、最近是否被修改、segment 类型、索引参数、向量字段信息尽量减少读写互斥——这是高并发查询路径上的典型锁设计。6.4 Data Sync Service流驱动的数据同步骨架把上面的结构串起来的执行者是dataSyncServicetype dataSyncService struct { ctx context.Context mu sync.Mutex // guards FlowGraphs collectionFlowGraphs map[UniqueID]map[Channel]*queryNodeFlowGraph // map[collectionID]flowGraphs partitionFlowGraphs map[UniqueID]map[Channel]*queryNodeFlowGraph // map[partitionID]flowGraphs streamingReplica ReplicaInterface tSafeReplica TSafeReplicaInterface msFactory msgstream.Factory }其本质是一个按 collection/partition channel 维度组织的数据流图FlowGraph管理器每个queryNodeFlowGraph对应一个collection/partition, channel对的消费流水线从 MsgStream 拉取插入/删除日志 → 更新 growing segment → 推进 tSafestreamingReplica提供对第 6.1 节 replica 的并发安全读写接口tSafeReplica管理每个 collection 的 tSafe 水位msFactorymsgstream 工厂为节点创建底层消息流客户端对应消息中间件如 Pulsar/Kafka 的抽象其总体设计见 chap04_message_stream.md。tSafe 的推进正是由 FlowGraph 在每个消费周期末尾完成的只有某 channel 在该时间戳之前的日志都被处理完tSafe 才能越过该时间戳。这为第 4 节所述GuaranteeTimestamp语义提供了执行端支撑——查询节点用 tSafe 回答我能否立即响应这次查询。7. 从 2.0 到当前仓库查询架构的演进对照chap07 是理解 Milvus 查询体系的极佳入门口但当前仓库master 分支的实现已经历显著演进读者在对照源码时应注意以下对应关系协调层internal/querycoordv2/取代了早期 QueryCoord 的单体编排逻辑。该目录中包含的子包与文件体现了新架构的关注点dist数据分布视图、segmentsegment 调度、collection集合级协调与负载均衡、channel 管理等整体以目标分布 实际分布 校正动作的 controller 循环取代了 2.0 中偏命令式的加载/释放逻辑执行层internal/querynodev2/取代了早期 QueryNode。其顶层文件server.go、services.go、handlers.go仍在实现与 chap07 一脉相承的LoadSegments / WatchDmChannels / AddQueryChannel等职责但内部组织改为delegator/查询委托与结果汇集、segments/segment 生命周期、pipeline/增量消费流水线、qnview/、pkoracle/等子包。其中pkoracle/正是pkFilter主键 Bloom Filter 去重思想的延续与强化协议层文档中的querypb各消息与PartitionState枚举仍可在此仓库的 pkg/proto/querypb/query_coord.pb.go 中找到证明接口契约的总体形态具备跨版本的稳定性消息通道模型2.0 中request/result 双通道 MsgStream 中转的查询分发形态在后继版本中逐步收敛为 Proxy 直连查询协调者/节点的查询调度与 delegator 汇聚机制以降低长链路延迟。需要强调的是本文对演进部分的描述是基于当前仓库目录结构的观察与推断不构成对新版内部行为的断言若需深入新架构建议直接阅读internal/querycoordv2/与internal/querynodev2/下对应源码并结合 developer_guides/README.md 中其余章节如数据流、时间同步机制拼出全貌。8. 小结理解查询子系统的三把钥匙读完 chap07 及本文的展开可以用三句话概括 Milvus 查询子系统的设计精髓分层协调QueryCoord 掌握数据分布与加载状态通过LoadSegments / WatchDmChannels / ReleaseSegments等控制 RPC 指挥各 QueryNode通过GetPartitionStates / GetSegmentInfo观测执行结果通道解耦SearchMsg / RetrieveMsg 经 request 通道分发、经 result 通道回传查询语义GuaranteeTimestamp与数据新鲜度QueryNode 侧 tSafe通过时间戳对齐让流式数据系统能提供可预期的一致性副本即状态collectionReplica 把分布式数据布局落地为节点内可直接查询的内存结构而 segment 状态机、索引/字段元数据与多把细粒度锁的设计是支撑高并发查询路径工程质量的具体体现。沿文档脉络继续深入可参阅同一归档目录下的 chap05_proxy.md请求入口如何把查询写入通道、chap08_binlog.md 与 chap09_data_coord.md数据侧如何产出 segment以及 how-guarantee-ts-works.md时间戳一致性机制的完整说明。【免费下载链接】milvusMilvus is a high-performance, cloud-native vector database built for scalable vector ANN search项目地址: https://gitcode.com/GitHub_Trending/mi/milvus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表