milvus學習筆記

本文主要由AI生成,請注意自己查看源代碼校驗。

Milvus v2.4+ 系統架構概覽

Milvus 采用分布式微服務架構,將計算層(Proxy、QueryCoord、QueryNode、IndexCoord、DataCoord、DataNode 等)與存儲層(Pulsar、MinIO/S3、etcd)分離,實現高并發、高可用和水平擴展。在查詢場景下,查詢請求首先經過前端 Proxy,由 Proxy 調度到后端查詢服務,再由 QueryNode 在數據分片(segment)上并行執行向量檢索,最后匯總結果返還給客戶端。總體架構示意如圖所示,重點標出了 Proxy、QueryCoord、QueryNode、DataCoord 等模塊及它們之間通過 gRPC 和消息隊列(如 Pulsar)通信的路徑。

圖1:Milvus 存算分離架構示意(Proxy -> 消息隊列 -> DataNode -> 對象存儲 -> QueryNode)

整體而言,Milvus 將寫流程和讀流程分離:寫入時,客戶端經由 Proxy 將數據寫入日志流(Pulsar),DataNode 消費寫日志并生成 segment(上傳到對象存儲),DataCoord/QueryCoord 收集和管理 segment;查詢時,客戶端經由 Proxy 發起檢索請求,Proxy 將查詢信息作為消息放入查詢通道(QueryChannel),各個 QueryNode 訂閱該通道接收查詢。在查詢前,QueryCoord 會根據 DataCoord 提供的 segment 信息對 QueryNode 做負載均衡(按 segment 或通道分配)。整個系統中,etcd 用于存儲元數據和服務發現,Pulsar 用作日志 broker(可替換為 Kafka 等),MinIO/S3 作為大文件存儲(segment、索引等)。

Proxy 模塊源碼結構

Proxy 作為客戶端訪問層,負責接收各種客戶端請求(DML、查詢、DDL 等),做校驗和預處理后分發給后端服務。其核心結構體在 internal/proxy 包中定義,包含如下主要成員:

type Server struct {ctx                context.Contextproxy              types.ProxyComponent      // 實現 proxy 功能的接口(對外暴露 gRPC 服務)rootCoordClient    types.RootCoordClient    // gRPC 客戶端:RootCoorddataCoordClient    types.DataCoordClient    // gRPC 客戶端:DataCoordqueryCoordClient   types.QueryCoordClient   // gRPC 客戶端:QueryCoord// ... 其他成員 ...
}

其中,types.ProxyComponent 接口由 internal/proxy/proxy.go 中的 Proxy 結構體實現。ServerRun() 方法啟動 gRPC 服務并注冊各類任務處理入口。對于向量檢索(Search)請求,Proxy 內部會生成一個 SearchTask(位于 internal/proxy/task_search.go),將用戶的查詢參數(如集合 ID、向量、Top-K、過濾表達式等)封裝成任務,然后將該任務發送給調度器或下游組件。在新版 Milvus 中,Proxy 并不直接執行搜索邏輯,而是根據查詢信息將查詢消息發往 Pulsar 的查詢通道(QueryChannel)。同時,Proxy 維護對 RootCoord/DataCoord/QueryCoord 的客戶端,用于獲取集合元數據、segment 分布、時間戳等信息。例如,在 LoadCollection 操作中,Proxy 會先調用 RootCoord 創建加載任務,再通過 QueryCoord 獲取需要加載的 segment 信息。總之,Proxy 起到“入口和匯聚”作用,無狀態地對外提供統一服務。

QueryCoord 模塊源碼結構

QueryCoord 是查詢協調節點,負責管理整個查詢集群的拓撲和負載均衡,以及查詢使用的 segment 分配和增量數據(Growing Segment)切換。其核心結構體位于 internal/querycoord 包中,主要成員包括:

type Server struct {queryCoord   types.QueryCoordComponent  // 實現 querycoord 功能的接口dataCoord    types.DataCoordClient      // gRPC 客戶端:DataCoordrootCoord    types.RootCoordClient      // gRPC 客戶端:RootCoord// ... 其他成員 ...
}

其中,types.QueryCoordComponent 接口由 internal/querycoord/query_coord.go 中的 QueryCoord 結構體實現。Server.Run() 啟動 gRPC 服務,處理來自 Proxy 或客戶端的查詢加載等請求。典型的功能包括:LoadCollection(預加載指定集合到查詢集群)和Search(調度查詢任務)等。當用戶調用 collection.load() 時,Proxy 會將加載請求轉發給 QueryCoord。QueryCoord 首先通過 dataCoord.GetRecoveryInfo() 獲取集合在存儲中的已封存段(Sealed Segment)及對應的檢查點;然后根據配置選擇“按段分配”或“按通道分配”策略,將不同的封存段 (或日志通道) 分配到各個 QueryNode 上。QueryCoord 的任務調度器 (segment allocatorchannel allocator) 負責這一步驟。此外,QueryCoord 還負責監控 QueryNode 的負載,觸發流式到封存段的轉換(handoff),以及均衡重分配。官方文檔指出:“QueryCoord 管理查詢節點的拓撲和負載平衡,并處理從增長段到封存段的切換”。在代碼層面,internal/querycoord 下的 querycoordsegment_allocatorchannel_allocator 等包實現了以上邏輯。

QueryNode 模塊源碼結構

QueryNode 是實際執行查詢計算的工作節點,負責在加載到本地的 segment 數據上運行向量檢索。其核心代碼位于 internal/querynodev2(Milvus 2.x 采用 v2 版本實現)。一個 QueryNode 進程啟動時,會初始化以下主要組件:流圖(FlowGraph)用于處理增量數據,索引服務用于處理已封存的數據檢索,和 Segment Manager 管理加載的 segment。Milvus 文檔中描述:“QueryNode 訂閱日志代理獲取增量日志,將其轉換為增長段,并從對象存儲加載歷史數據,在向量和標量數據之間運行混合搜索”。

在實現上,QueryNode 包括:server.go 定義了 QueryNode 結構體(實現 types.QueryNodeComponent 接口),負責啟動 gRPC 服務和管理子模塊;flowgraph 子包實現了增長段(Growing Segment)的流式數據接收與過濾;delegate 子包負責封裝和分發具體的搜索請求到適當的 segment 或索引;segcore(SegCore)則提供 C++ 的向量檢索核心調用。QueryNode 的主要方法包括 Search() (接受 QueryChannel 的查詢消息)、LoadSegments()(加載指定 segment 的數據到內存),以及定期從 DataCoord 讀取全局時間戳和消費位置,實現讀取增量數據并觸發持久化/封存。在并發執行向量檢索時,QueryNode 會對本地所有加載的封存段并行搜索,然后與增長段(當前寫入的數據)一起做融合,最后本地歸約(去重)輸出結果。可見,QueryNode 相對復雜,涉及流式處理和檢索執行兩大功能。

一次完整的向量檢索流程

下面按步驟說明客戶端一次查詢請求在 Milvus 中的流轉路徑:

  1. 客戶端請求 -> Proxy:客戶端通過 SDK 發起 Search 請求到 Proxy(gRPC)。Proxy 接收后,將請求信息(包括集合 ID、查詢向量、搜索參數等)封裝成一個查詢消息,并寫入日志中間件(Pulsar)的查詢通道。同時,Proxy 可從 RootCoord/DataCoord 獲取集合的元數據和可用 segment 列表,為后續的調度做準備。

  2. (預先)Load Collection -> QueryCoord:在發起搜索前,如果用戶調用了 collection.load(),Proxy 會觸發 QueryCoord 的加載操作。QueryCoord 向 DataCoord 查詢集合所有已封存段(和各段的消費檢查點),然后執行負載分配。例如,按段分配時將不同封存段分配給不同 QueryNode;按通道分配時讓 QueryNode 訂閱不同的 DMChannel。在此步驟結束后,相關 QueryNode 已從對象存儲加載了對應的歷史數據段(封存段),并訂閱了增量日志通道(收到新的寫入數據)。

  3. QueryCoord 分配 -> QueryNode 訂閱:QueryCoord 調度后,各 QueryNode 會執行對應的 LoadSegmentsWatchChannels 操作,準備好查詢環境。每個 QueryNode 都在其本地維持了若干封存段(Sealed Segment)和對應的增長段(Growing Segment)(參見圖2)。

圖2:QueryCoord 為每個 QueryNode 分配封存段和日志通道示意。QueryNode1 加載了 S1、S3 等歷史段,并訂閱了 DMChannel1;QueryNode2 加載了 S2、S4,并訂閱 DMChannel2。最終每個節點在本地同時擁有歷史數據和增量流數據。

  1. QueryProxy 將查詢推送至查詢通道:客戶端的查詢請求已經寫入 Pulsar 查詢通道后,各 QueryNode 會監聽此通道并取出查詢消息。在消息中包含了執行時間戳等信息。Milvus 首先比較當前服務時間戳(service_ts)與查詢消息中的保證時間戳(guarantee_ts)。只有當 service_ts >= guarantee_ts 時,才執行查詢;否則該查詢消息會暫時“懸掛”直到達到條件。

  2. QueryNode 執行檢索并歸約:當查詢消息符合執行條件后,每個 QueryNode 并行地在本地的歷史數據和增量數據上執行搜索。這包括對已經加載的封存段(離線歷史數據)和正接收寫入的增長段(在線流數據)分別進行搜索。由于兩者可能重疊,QueryNode 內部會做一次“本地歸約”(Local Reduce)去重。搜索完成后,各 QueryNode 將本地結果發布到結果通道(ResultChannel)。此時,結果消息中包含了本節點所搜索的封存段和通道信息。

  3. Proxy 聚合返回結果:Proxy 訂閱結果通道,收集來自所有 QueryNode 的結果集。收到后,Proxy 會做一次全局歸約(Global Reduce),去除不同節點間的重復結果。為確保結果完整性,Proxy 通過結果消息中的字段跟蹤是否所有封存段和通道的數據都已返回。當條件滿足后,Proxy 將最終合并排序后的 Top-K 結果返回給客戶端。整個流程中,Proxy 僅負責路由和匯總;QueryCoord 只在查詢準備階段調度;真正的搜索計算由各 QueryNode 執行。

模塊間調用鏈示意

以下偽代碼描述了上述交互的主要調用順序(忽略錯誤處理和并發細節):

// Proxy 接收到客戶端的搜索請求
func ProxyHandleSearch(req QueryRequest) {// 1. 向 RootCoord 請求集合元數據(例如分片、索引信息)collectionInfo := RootCoord.GetCollectionInfo(req.CollectionID)// 2. 將查詢信息封裝為消息寫入 Pulsar 查詢通道Pulsar.Publish(QueryChannel, req)// 3. 監聽結果通道,收集 QueryNode 返回結果results := collectResultsFromChannel(ResultChannel)// 4. 對所有 QueryNode 的結果做歸約并返回merged := globalReduce(results)return merged
}// QueryCoord 預加載流程(LoadCollection)
func QueryCoordLoad(collectionID) {// 從 DataCoord 獲取所有已封存段和檢查點segments := DataCoord.GetRecoveryInfo(collectionID)// 選擇分配策略(按段或按通道)// 將 segment 列表分配給不同的 QueryNodeassignments := allocateSegmentsToNodes(segments)// 通知各 QueryNode 加載數據或訂閱通道for each node, segs in assignments:node.LoadSegments(segs)
}// QueryNode 搜索處理
func QueryNodeOnQueryMessage(msg QueryRequest) {if serviceTS < msg.GuaranteeTS {// 不滿足時間條件,等待return}// 在本地封存段和增長段上并行檢索resultsOffline := searchSealedSegments(msg.Vector, req)resultsStream := searchGrowingSegments(msg.Vector, req)localResults := localReduce(resultsOffline, resultsStream)// 發布到結果通道Pulsar.Publish(ResultChannel, localResults)
}

該調用鏈中,關鍵的是 Proxy、QueryCoord、QueryNode 三層協作:Proxy 負責接收請求與返回結果,QueryCoord 負責查詢準備與調度,QueryNode 負責具體檢索執行。

代碼目錄與主要文件(參考)

Milvus 倉庫 internal 目錄下包含各組件的實現子目錄,其中與查詢相關的主要路徑有:

  • internal/proxy/:Proxy 服務實現,包括 proxy.go(Proxy 結構體、接口)、task_search.go(SearchTask 實現)等。

  • internal/querycoord/:QueryCoord 服務實現,包括 query_coord.go(QueryCoord 結構體、接口)、segment_allocator/channel_allocator/ 等調度邏輯。

  • internal/querynodev2/:QueryNode 服務實現,包括 server.go(QueryNode 結構體、接口)、flowgraph/(流式處理)、delegate/(查詢代理)、segments/(本地 segment 管理)等。

下圖為 Milvus 源碼(部分)目錄結構示意:

internal/
├── proxy/
│   ├── proxy.go          # ProxyComponent 實現(types.ProxyComponent)
│   ├── task_search.go    # SearchTask 邏輯
│   └── ...              
├── querycoord/
│   ├── query_coord.go    # QueryCoordComponent 實現(types.QueryCoordComponent)
│   ├── segment_allocator/
│   └── channel_allocator/
│   └── ...
├── querynodev2/
│   ├── server.go         # QueryNodeComponent 實現(types.QueryNodeComponent)
│   ├── flowgraph/        # 增量數據流式處理
│   ├── delegate/         # 查詢請求分發
│   ├── segments/         # 本地 Segment 管理
│   └── ...
└── datacoord/            # DataCoord 服務(管理存儲相關)└── ...

從以上目錄可見,每個組件都用一個 Server 結構體啟動 GRPC 服務,并持有對應的客戶端接口,如 ProxyServer 包含 rootCoordClientqueryCoordClient 等。組件間通過 gRPC 和 Pulsar 消息進行協同,如 Proxy 調用 QueryCoord.LoadCollection 獲取 segment 信息,QueryCoord 調用 DataCoord.GetRecoveryInfo 獲取段信息,QueryNode 從 Pulsar 查詢通道接收 Search 請求等。

參考資料

  • Milvus 官方文檔與博客:《Milvus 架構概覽》《QueryCoord 相關配置》《實時查詢解析》等。

  • Zilliz/Milvus GitHub 代碼:internal/proxyinternal/querycoordinternal/querynodev2 包。

  • 開源社區文章:Milvus 源碼解析博客(見 “SearchTask”、“實時查詢” 部分)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81335.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81335.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81335.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用教程:8x16模擬開關陣列可級聯XY腳雙向導通自動化接線

以下通過點亮LED進行基本使用流程演示&#xff0c;實際可以連接復雜外設&#xff08;SPI、CAN、ADC等&#xff09; 單模塊使用 RX、TX、5V和GND接到串口模塊&#xff1b;X5接5V&#xff1b;Y2接LED;LED-接GND 串口模塊插上電腦后&#xff0c;LED沒有亮&#xff1b;因為此時模…

HarmonyOS NEXT~鴻蒙應用上架指南:HarmonyOS應用發布全流程解析

HarmonyOS NEXT&#xff5e;鴻蒙應用上架指南&#xff1a;HarmonyOS應用發布全流程解析 引言 隨著華為鴻蒙操作系統(HarmonyOS)生態的快速發展&#xff0c;越來越多的開發者希望將自己的應用上架到鴻蒙應用市場。本文將詳細介紹鴻蒙應用上架的全流程&#xff0c;幫助開發者順…

20250517 我設想一個空間,無限大,空間不與其中物質進行任何作用,甚至這個空間能容納可以伸縮的空間

1.我設想一個空間&#xff0c;無限大&#xff0c;空間不與其中物質進行任何作用&#xff0c;甚至這個空間能容納可以伸縮的空間 您設想的這個空間具有一些有趣的特點&#xff1a; 無限大&#xff1a;空間本身沒有邊界或限制&#xff0c;理論上可以容納無限多的物質或結構。非…

使用 Kaniko來構建鏡像

使用 Kaniko來構建鏡像 Kaniko 是一種專注于容器鏡像構建的開源工具&#xff0c;其核心設計理念與 Docker 存在顯著差異。以下從功能定位、技術實現和適用場景三方面進行對比分析&#xff1a; 一、Kaniko 的核心特性 無需 Docker 守護進程 Kaniko 直接在容器或 Kubernetes 集…

webman用nginx代理靜態json文件的異步跨域

場景 有.json文件置于webman的public目錄下&#xff0c;使用了nginx做代理&#xff0c;直接訪問文件是可以正常加載的&#xff0c;但跨域瀏覽器就無法加載文件。 nginx配置 文件是否存在于跟目錄&#xff0c;存在則設置請求頭&#xff0c;不存在則將請求交給webman處理即可。…

JDK 21新特性全面解析

Java Development Kit (JDK) 21作為Oracle長期支持(LTS)版本&#xff0c;于2023年9月正式發布&#xff0c;帶來了多項令人振奮的新特性和改進。本文將全面介紹JDK 21中的主要更新&#xff0c;幫助開發者了解如何利用這些新功能提升開發效率和代碼質量。 一、虛擬線程(Virtual …

如何選擇高性價比的 1T 服務器租用服務?

選擇高性價比的 1T 服務器租用服務?&#xff0c;可參考以下內容&#xff1a; 1、根據需求選配置? 明確自身業務需求是關鍵。若為小型網站或輕量級應用&#xff0c;數據存儲與處理需求不高&#xff0c;選擇基礎配置服務器即可。如個人博客網站&#xff0c;普通的 Intel Xeon …

JavaScript性能優化實戰(11):前沿技術在性能優化中的應用

引言 隨著Web應用復雜度和性能需求不斷提高,傳統的JavaScript優化技術已經無法滿足某些高性能計算場景的需求。本文將深入探討前沿Web技術如何突破JavaScript的性能瓶頸,為Web應用提供接近原生應用的性能體驗。從底層計算到圖形渲染,從并發處理到動畫優化,我們將通過實際案…

package.json 和 package-lock.json 的區別

package.json?? ??作用?? ??聲明項目元數據??&#xff1a;如項目名稱、版本、描述、入口文件等。??定義依賴范圍??&#xff1a;在 dependencies 和 devDependencies 中聲明項目??直接依賴??的包及其??版本范圍??&#xff08;如 ^1.2.3&#xff09;。??…

Rollup入門與進階:為現代Web應用構建超小的打包文件

我們常常面臨Webpack復雜配置或是Babel轉譯后的冗余代碼&#xff0c;結果導致最終的包體積居高不下加載速度也變得異常緩慢&#xff0c;而在眾多打包工具中Rollup作為一個輕量且高效的選擇&#xff0c;正悄然改變著這一切&#xff0c;本文將帶你深入了解這個令人驚艷的打包工具…

基于C#的MQTT通信實戰:從EMQX搭建到發布訂閱全解析

MQTT(Message Queueing Telemetry Transport) 消息隊列遙測傳輸&#xff0c;在物聯網領域應用的很廣泛&#xff0c;它是基于Publish/Subscribe模式&#xff0c;具有簡單易用&#xff0c;支持QoS&#xff0c;傳輸效率高的特點。 它被設計用于低帶寬&#xff0c;不穩定或高延遲的…

Mysql數據庫之集群進階

一、日志管理 5.7版本自定義路徑時的文件需要自己提前創建好文件&#xff0c;不會自動創建&#xff0c;否則啟動mysql會報錯 錯誤日志 rpm包(yum) /var/log/mysql.log 默認錯誤日志 ###查詢日志路徑 [rootdb01 ~]# mysqladmin -uroot -pEgon123 variables | grep -w log_e…

當硅基存在成為人性延伸的注腳:論情感科技重構社會聯結的可能性

在東京大學機器人實驗室的檔案室里&#xff0c;保存著一份泛黃的二戰時期設計圖——1943年日本陸軍省秘密研發的“慰安婦替代品”草圖。這個誕生于戰爭陰霾的金屬軀體&#xff0c;與2025年上海進博會上展出的MetaBox AI伴侶形成時空對話&#xff1a;當人類將情感需求投射于硅基…

5月17日

這幾天不知道為啥沒更新。可能是玩得太瘋了。或者是考試有點集中&#xff1f;&#xff1f; 線性代數開課了&#xff0c;英語昨天完成了debate 昨天中午debate結束我們就出去玩了&#xff0c;去的那里時光民俗&#xff0c;別墅很好&#xff0c;770平米&#xff0c;但是缺點是可…

FIFO的應用案例(基于Zephyr OS )

目錄 概述 1. 軟硬件環境 1.1 軟件開發環境 1.2 硬件環境 2 FIFO的函數接口 3 FIFO的應用函數實現 3.1 實現步驟 3.2 代碼設計 3.3 測試代碼實現 3.4 源代碼文件 4 編譯和測試 4.1 編譯代碼 4.2 測試 概述 本文介紹了在nRF52832開發板上使用Zephyr操作系統進行…

AWS Elastic Beanstalk部署極簡Spring工程(EB CLI失敗版)

棄用 這里我沒有走通EB CLI方式部署。 問題 最近又加入了AWS項目組&#xff0c;又要再次在AWS云上面部署Spring服務&#xff0c;我這里使用的使用AWS中國云。需要使用AWS Elastic Beanstalk部署一個極簡Spring工程。 EB CLI安裝 安裝EB CLI之前需要先在本地安裝好Git&…

粒子群算法(PSO算法)

粒子群算法概述 1.粒子群優化算法&#xff08;Particle Swarm Optimization&#xff0c;簡稱PSO&#xff09;。粒子群優化算法是在1995年由Kennedy博士和Eberhart博士一起提出的&#xff0c;它源于對鳥群捕食行為的研究。 2.基本核心是利用群體中的個體對信息的共享從而使得整…

leetcode2934. 最大化數組末位元素的最少操作次數-medium

1 題目&#xff1a;最大化數組末位元素的最少操作次數 官方標定難度&#xff1a;中 給你兩個下標從 0 開始的整數數組 nums1 和 nums2 &#xff0c;這兩個數組的長度都是 n 。 你可以執行一系列 操作&#xff08;可能不執行&#xff09;。 在每次操作中&#xff0c;你可以選…

Elasticsearch 官網閱讀之 Term-level Queries

Term-level Queries 參考&#xff1a;https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-exists-query 一、Term Query Term Query 是 term 精準查詢。需要注意的是&#xff0c;在進行 Term Query 的時候&#xff0c;要避免 text 類型的字段&#x…

信貸域——互聯網金融業務

摘要 本文深入探討了信貸域全托與半托業務的定義、特點、適用場景及注意事項&#xff0c;并分析了互聯網金融核心信息流的多個方面&#xff0c;包括資金流、信息流、風險流、合規流、物流、技術流和商流&#xff0c;還闡述了金融系統“斷直連”業務的相關內容&#xff0c;以及…