<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Milvus 解析 | 前所未有的 Milvus 源碼架構(gòu)解析

          共 12863字,需瀏覽 26分鐘

           ·

          2022-02-20 14:12



          ?? 者按:

          Deep Dive 是由 Milvus 社區(qū)發(fā)起的代碼解析系列直播,針對(duì)開源數(shù)據(jù)庫(kù) Milvus 整體架構(gòu)開放式解讀,與社區(qū)交流與分享 Milvus 最核心的設(shè)計(jì)理念。通過(guò)本期分享,你可以了解到云原生數(shù)據(jù)庫(kù)背后的設(shè)計(jì)理念,理解 Milvus 相關(guān)組件與依賴,了解 Milvus 多種應(yīng)用場(chǎng)景。

          講師簡(jiǎn)介:

          欒小凡,Zilliz 合伙人、工程總監(jiān),LF AI & Data 基金會(huì)技術(shù)咨詢委員成員。他先后任職于 Oracle 美國(guó)總部、軟件定義存儲(chǔ)創(chuàng)業(yè)公司 Hedvig 、阿里云數(shù)據(jù)庫(kù)團(tuán)隊(duì),曾負(fù)責(zé)阿里云開源 HBase 和自研 NoSQL 數(shù)據(jù)庫(kù) Lindorm 的研發(fā)工作。欒小凡擁有康奈爾大學(xué)計(jì)算機(jī)工程碩士學(xué)位。


          視頻版講解請(qǐng)戳 ??

          本期分享分為四個(gè)部分:
          1. 我們?yōu)槭裁葱枰?Milvus ?為什么它被稱為下一代人工智能基礎(chǔ)設(shè)施?
          2. Milvus 2.0 的設(shè)計(jì)理念
          3. Milvus 2.0 的概覽與模塊劃分
          4. Milvus 代碼閱讀注意事項(xiàng)


            我們?yōu)槭裁葱枰?Milvus?

          非結(jié)構(gòu)化數(shù)據(jù)處理流程

          Milvus 為解決非結(jié)構(gòu)化數(shù)據(jù)的檢索問(wèn)題而生:海量的非結(jié)構(gòu)化數(shù)據(jù)一般會(huì)存儲(chǔ)在分布式文件系統(tǒng)或?qū)ο蟠鎯?chǔ)上,之后通過(guò)深度學(xué)習(xí)網(wǎng)絡(luò)完成推理,將這些非結(jié)構(gòu)數(shù)據(jù)轉(zhuǎn)化成 embedding 向量,并在向量空間內(nèi)完成近似性檢索,從而發(fā)現(xiàn)數(shù)據(jù)背后的一些特征。
          整個(gè)數(shù)據(jù)處理流程如下圖所示。比如,有很多原始的食物圖片,通過(guò)卷積神經(jīng)網(wǎng)絡(luò)做訓(xùn)練和推理,為每一幅照片得出一組向量,再把這些向量按照空間中的近似維度做排序,最后得到這樣的結(jié)果:最上面一排是一些長(zhǎng)得像薯?xiàng)l的東西,中間都是一些長(zhǎng)得像拉面的東西,底下都是長(zhǎng)得像壽司的東西。也就是說(shuō),圖片這種非結(jié)構(gòu)化數(shù)據(jù),經(jīng)過(guò)深度學(xué)習(xí)處理之后,轉(zhuǎn)化成了embedding 向量,并通過(guò)在向量空間的近似度比對(duì)來(lái)表征其相似性,這在很大程度上能跟人類理解的近似度是高度一致的。


          向量與標(biāo)量

          傳統(tǒng)的標(biāo)量數(shù)據(jù)和 Milvus 面向的向量數(shù)據(jù)之間,到底有哪些不同呢?
          從基本操作上來(lái)講,對(duì)于標(biāo)量數(shù)據(jù),針對(duì)數(shù)值類數(shù)據(jù)一般會(huì)做加減乘除的操作;對(duì)字符串類型的數(shù)據(jù)一般會(huì)做一些 term 的匹配, 或者一些類似 like 的近似匹配,抑或一些前綴匹配。
          而針對(duì)向量數(shù)據(jù)而言,很少進(jìn)行這種 100% 的完全匹配,更多是看近似度,也就是高維空間下的距離。較常見的距離表示有余弦距離、歐式距離等。空間中向量之間的距離,很大程度上能表示非結(jié)構(gòu)化數(shù)據(jù)之間的相似度。
          除了對(duì)數(shù)據(jù)的操作會(huì)有很大不同以外,數(shù)據(jù)的組織方式也會(huì)有很大不同。如,傳統(tǒng)數(shù)據(jù)很容易比較大小,無(wú)論是數(shù)值類,還是字符串,都可以通過(guò)二叉樹或者 skip list 的方式排列組合,然后做二分查找。對(duì)于向量數(shù)據(jù)來(lái)講,則更加復(fù)雜,因?yàn)樗S度較高,很難像傳統(tǒng)的數(shù)值類數(shù)據(jù)一樣通過(guò)排序的方式做加速,往往需要一些特殊的索引結(jié)構(gòu)和存儲(chǔ)方式。


          常見的向量索引方式

          常見的向量的索引方式有哪些呢?
          1) FLAT file,也就是大家常說(shuō)的暴力搜索,這種方式是典型的犧牲性能和成本換取準(zhǔn)確性,是唯一可以實(shí)現(xiàn) 100% 召回率的方式,同時(shí)可以較好地使用顯卡等異構(gòu)硬件加速。
          2) Hash based,基于 locality sensitive hashing 將數(shù)據(jù)分到不同的哈希桶中。這種方式實(shí)現(xiàn)簡(jiǎn)單,性能較高,但是召回率不夠理想。
          3) Tree based,代表是 KDTree 或者 BallTree,通過(guò)將高維空間進(jìn)行分割,并在檢索時(shí)通過(guò)剪枝來(lái)減少搜索的數(shù)據(jù)量,這種方式性能不高,尤其是在維度較高時(shí)性能不理想。
          4) 基于聚類的倒排,通過(guò) k-means 算法找到數(shù)據(jù)的一組中心點(diǎn),并在查詢時(shí)利用查詢向量和中心點(diǎn)距離選擇部分桶進(jìn)行查詢。倒排這一類又擁有很多的變種,比如可以通過(guò) PCA 將數(shù)據(jù)進(jìn)行降維,進(jìn)行標(biāo)量量化,或者通過(guò)乘積量化 PQ 將數(shù)據(jù)降精度,這些都有助于減少系統(tǒng)的內(nèi)存使用和單次數(shù)據(jù)計(jì)算量。
          5) NSW(Navigable Small World)圖是一種基于圖存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu),這種索引基于一種樸素的假設(shè),通過(guò)在構(gòu)建圖連接相鄰的友點(diǎn),然后在查詢時(shí)不斷尋找距離更近的節(jié)點(diǎn)實(shí)現(xiàn)局部最優(yōu)。在 NSW 的基礎(chǔ)上,HNSW(Navigable Small World)圖借鑒了跳表的機(jī)制,通過(guò)層狀結(jié)構(gòu)構(gòu)建了快速通道,提升了查詢效率。


          Milvus:為 AI 而生的數(shù)據(jù)庫(kù)

          Milvus 是專為 AI 而生的數(shù)據(jù)庫(kù),下圖就是典型的 Milvus 在非結(jié)構(gòu)化數(shù)據(jù)鏈路中的應(yīng)用場(chǎng)景。
          它支持的數(shù)據(jù)分為兩類,一類就是需要比對(duì)的數(shù)據(jù),另一類就是需要真正去做查詢的數(shù)據(jù)。這些數(shù)據(jù)通過(guò) Encoder 生成最終的 embedding 向量,向量通過(guò) Milvus 做查詢。所有的寫入會(huì)轉(zhuǎn)化成文件,并最終存儲(chǔ)在對(duì)象存儲(chǔ)上面。查詢的過(guò)程中, search 基本上是純內(nèi)存的操作,利用一些內(nèi)存的索引找到距離比較近的向量,然后再對(duì)這些向量會(huì)做一些讀盤操作,拿到數(shù)據(jù)。
          除了實(shí)現(xiàn)基本的向量搜索功能,Milvus 也是一個(gè)數(shù)據(jù)庫(kù),可以實(shí)現(xiàn)動(dòng)態(tài)的增刪改查。未來(lái),社區(qū)也計(jì)劃去做像 Snapshot、備份、多租戶之類更加常見的數(shù)據(jù)庫(kù)功能。
          其次,相對(duì)于傳統(tǒng)的向量檢索庫(kù),Milvus 支持標(biāo)量和向量數(shù)據(jù)的混合查詢。傳統(tǒng)向量搜索的 Index 通常只針對(duì)向量數(shù)據(jù),但是我們發(fā)現(xiàn)很多用戶希望同時(shí)使用標(biāo)量和向量,給一些標(biāo)量的限制條件做過(guò)濾,再在這個(gè)基礎(chǔ)上針對(duì)向量數(shù)據(jù)做查詢。
          此外,借助云基礎(chǔ)設(shè)施,Milvus 實(shí)現(xiàn)了高度可擴(kuò)展性和健壯性,并具備很高的彈性,后面我們將具體討論 Milvus 是如何實(shí)現(xiàn)這一能力的。
          Milvus “不是”什么?Milvus 首先不是一個(gè)關(guān)系型數(shù)據(jù)庫(kù),不會(huì)支持特別復(fù)雜的 JOIN 之類的查詢,也不會(huì)支持 ACID 的事務(wù)。Milvus 主要是做向量域的近似查詢。同時(shí),Milvus 也不是一個(gè)搜索引擎,跟傳統(tǒng)的 Elasticsearch、Solr 之間也有很大區(qū)別。Milvus 針對(duì)的是 embedding 向量數(shù)據(jù),而不是傳統(tǒng)的文本格式的數(shù)據(jù)。對(duì)于文本來(lái)說(shuō),Milvus 做的是基于語(yǔ)義的檢索,而不是基于關(guān)鍵詞的檢索。


          2.0 Tradeoffs

          Milvus 2.0 在 1.0 版本做了大幅的重構(gòu),為什么會(huì)有這樣大的升級(jí)?社區(qū)在做 Milvus 1.0 版本的過(guò)程中,遇到了一些比較大的 Tradeoffs。
          在設(shè)計(jì)一個(gè)分布式系統(tǒng)的過(guò)程中,一定會(huì)面臨一些取舍。比較經(jīng)典的數(shù)據(jù)庫(kù)的取舍方法是 CAP,也就是一致性(Consistency)、可用性(Availability)、分區(qū)容錯(cuò)性(Partition tolerance)。通常情況下,網(wǎng)絡(luò) Partation 不能解決的情況下,用戶往往就只能在一致性和可用性之間 tradeoff 。比如傳統(tǒng)的 TP 數(shù)據(jù)庫(kù)往往會(huì)選擇一致性,一些 AP 數(shù)據(jù)庫(kù)或者 NoSQL 數(shù)據(jù)庫(kù)可能會(huì)選擇更高的可用性。
          對(duì)于 Milvus 來(lái)講,絕大多數(shù)用戶更多偏向可用性,對(duì)數(shù)據(jù)的實(shí)時(shí)可見沒有那么高的要求。在 CAP 這個(gè)理論基礎(chǔ)上,微軟提出了更新的理論“PACELC”:在網(wǎng)絡(luò)隔離性的基礎(chǔ)上,一致性和可用性之間存在 Tradeoff ;如果網(wǎng)絡(luò)不發(fā)生隔離的話,就還有另一層 Tradeoff,叫做一致性和 Latency 之間的一個(gè) Tradeoff。也就是說(shuō),如果網(wǎng)絡(luò)都是正常的,為了維持一致性,一定要犧牲可用性。比如說(shuō)跨城服務(wù)的情況下,如果要保證一致性的話,那一定需要做跨城讀寫。這個(gè)情況下, Latency 相對(duì)來(lái)講一定是比較高的。本身 Milvus 就是一個(gè)更加看重 Latency 的系統(tǒng),因此在大部分情況下,我們會(huì)選擇去犧牲一定的 一致性,也來(lái)實(shí)現(xiàn)可用性和 Latency 。
          除了傳統(tǒng)的 CAP 的理論之外,還有另一個(gè) CAP 的 Tradeoff ,就是 Cost、Accuracy 和 Performance。通常情況下,一個(gè)系統(tǒng)的實(shí)現(xiàn)成本基本上是恒定的。在這種情況下,更多程度上取決于所需查詢的精度和性能。目前看下來(lái),這兩類用戶各有各的選擇,有些用戶會(huì)傾向更精確,為此寧愿多花一點(diǎn)成本保證查詢是精確的。因此 Milvus 也提供了很多種索引的類型,大家可以根據(jù)自己在 CAP 方面不同的取舍,選擇更好的索引類型和系統(tǒng)參數(shù)。


          從引擎到數(shù)據(jù)庫(kù)

          Milvus 2.0 要解決的第二個(gè)問(wèn)題,是從一個(gè)引擎變成一個(gè)強(qiáng)大的數(shù)據(jù)庫(kù)。
          大家如果了解過(guò) InnoDB 和 MySQL 之間的關(guān)系,或者了解過(guò) Lucene 和 ES 之間的關(guān)系的話,相信就會(huì)很清楚個(gè)中邏輯。
          傳統(tǒng)數(shù)據(jù)庫(kù)主要解決功能問(wèn)題,比如 Milvus 本身也會(huì)依賴 Faiss、HNSWAnnoy 之類的開源的庫(kù)。這些庫(kù)更關(guān)注查詢的功能和性能。而 Milvus 除了要關(guān)注這些內(nèi)容之外,還需要關(guān)注很多其他的東西,比如如何做數(shù)據(jù)分片,如何保證數(shù)據(jù)的高可靠性,如何保證分布式系統(tǒng)有節(jié)點(diǎn)出現(xiàn)異常時(shí)如何恢復(fù),如何在一個(gè)大規(guī)模集群中實(shí)現(xiàn)負(fù)載均衡,如何查詢語(yǔ)句,如何做 Parse 和 Optimize。又如,系統(tǒng)做持久化存儲(chǔ),需要考量不同的數(shù)據(jù)存儲(chǔ)格式,而通常標(biāo)準(zhǔn)的庫(kù)是不會(huì)去考慮這些的。從用戶的角度出發(fā),需要一個(gè)更加易用、功能更加強(qiáng)大的組件,而不僅僅是一個(gè)更快的庫(kù)。


          為云而生

          Milvus 2.0 的第三個(gè)考量是擁抱云原生。
          過(guò)去十幾年,傳統(tǒng)數(shù)據(jù)庫(kù)基本采用 share nothing 的架構(gòu)。隨著 Snowflake 的出現(xiàn),很多數(shù)據(jù)庫(kù)采用了 shared storage ,越來(lái)越多的數(shù)據(jù)庫(kù)開始做存儲(chǔ)計(jì)算分離。Snowflake 給予業(yè)界很大啟發(fā),利用云上的基礎(chǔ)設(shè)施去做數(shù)據(jù)持久化,然后基于本地存儲(chǔ)做緩存,這種模這種模式被稱為 share something,獲得了很多產(chǎn)品的共識(shí)。
          另一個(gè)層面,利用 Kubernetes 管理執(zhí)行引擎,利用微服務(wù)的模式分拆讀、寫和其他服務(wù),也有利于各個(gè)組件分別彈性擴(kuò)展。Milvus 所有的數(shù)據(jù)庫(kù)執(zhí)行引擎目前與 Docker 和 Kubernetes 適配,包括匹配目前主流的微服務(wù)的設(shè)計(jì)模式。
          另一個(gè)很重要的趨勢(shì)是 Database as a Service。在做 Database 的過(guò)程中,我們發(fā)現(xiàn)很多用戶不僅關(guān)注數(shù)據(jù)庫(kù)的功能,還越來(lái)越多地關(guān)注數(shù)據(jù)庫(kù)如何做管理、計(jì)費(fèi)、可視化,數(shù)據(jù)遷移。數(shù)據(jù)庫(kù)不僅要提供傳統(tǒng)的增刪改查能力,還提供數(shù)據(jù)轉(zhuǎn)換、遷移、多租戶加密管理、計(jì)費(fèi)、限流、可視化、備份快找等更加多樣的服務(wù)。
          第三個(gè)重要的趨勢(shì)是協(xié)同一體化。Milvus 本身是一個(gè)負(fù)責(zé)系統(tǒng),我們也會(huì)依賴一些開源系統(tǒng)作為 Milvus 的組件, 比如使用 etcd 做元信息的存儲(chǔ),能使用 Message Queue 作為 Milvus 的數(shù)據(jù),或者說(shuō)把我們的增量數(shù)據(jù)導(dǎo)出。同時(shí)也希望可以跟一些 AI 的 Infra 結(jié)合,比如與 Spark 或者 Tensorflow 建立一種上下游的依賴關(guān)系;與一些流計(jì)算引擎結(jié)合,實(shí)現(xiàn)流批結(jié)合的方式,希望我們的用戶可以根據(jù)自己對(duì)實(shí)時(shí)性和效率的不同要求,有更多的選擇。


            Milvus 2.0 的設(shè)計(jì)理念

          日志即數(shù)據(jù)

          什么是日志呢?日志是一種只能追加、按照時(shí)間完全有序的記錄序列。以下圖為例,從左到右,左邊的數(shù)據(jù)是老的數(shù)據(jù),右邊的數(shù)據(jù)是新數(shù)據(jù),日志是按照時(shí)間維度排列的。在 Milvus 中,我們有一個(gè)全局的中心授時(shí)邏輯,發(fā)配全局唯一且自增的時(shí)間戳。
          這個(gè)時(shí)間戳有哪些功能?時(shí)間戳對(duì)事物隔離會(huì)有很大的好處,同時(shí),時(shí)間戳也可能會(huì)用來(lái)給數(shù)據(jù)做定序,比如說(shuō)一條刪除和一條寫入的數(shù)據(jù),到底哪個(gè)時(shí)間大,實(shí)際上是通過(guò)全局唯一的時(shí)間戳來(lái)定義的。
          有了這個(gè)日志序列后能做什么事情?
          理論上講,如果有兩個(gè)完全相同的確定性的進(jìn)程,從同一個(gè)狀態(tài)開始,以相同的順序去獲得相同的輸入,那么兩個(gè)進(jìn)程最終會(huì)生成相同的輸出并結(jié)束在相同的狀態(tài)。所謂結(jié)果,無(wú)論是內(nèi)存中的狀態(tài),還是磁盤上的狀態(tài),最終都是完全一致的。它的用途非常廣泛,最廣為人知的一個(gè)用途就是基于狀態(tài)機(jī)的復(fù)制算法,證明了“日志即數(shù)據(jù)”是很好的工作方式。


          表與日志的二象性

          日志和數(shù)據(jù)之間可以相互轉(zhuǎn)換的,它到底有什么作用呢?我們提出,表與日志之間存在二象性。表數(shù)據(jù)和日志數(shù)據(jù)是數(shù)據(jù)的兩面,表代表的是有界數(shù)據(jù),日志代表的是無(wú)界數(shù)據(jù)。日志可以被轉(zhuǎn)換為表數(shù)據(jù),Milvus 通過(guò) TimeTick 分離出處理窗口,并根據(jù)處理窗口聚合日志。
          日志的數(shù)據(jù)可以轉(zhuǎn)換成表的數(shù)據(jù),那么我們?nèi)绾瓮瓿蛇@個(gè)轉(zhuǎn)化呢?通過(guò)日志序列,我們把數(shù)據(jù)劃分成一個(gè)個(gè)窗口,根據(jù)這些窗口聚合成表的一個(gè)小文件,叫做 Log Snapshot。這些大件聚合起來(lái)叫做 Segment ,形成一個(gè)可以去單獨(dú)做 Load Balance 或者擴(kuò)展的單元。


          日志持久化

          另一個(gè)充滿挑戰(zhàn)的問(wèn)題是日志持久化。分布式數(shù)據(jù)庫(kù)日志的存儲(chǔ)往往依賴一些復(fù)制算法,比如:
          Aurora 就實(shí)現(xiàn)了底層的基于 Quorum 的一個(gè)持久化的日志系統(tǒng)。這個(gè) Quorum 算法邏輯也比較簡(jiǎn)單,只等兩個(gè)結(jié)果,讀的時(shí)候也只等兩個(gè)結(jié)果。只要讀和寫的副本數(shù)目大于總的副本數(shù)目,就一定能讀到一致性的結(jié)果。
          HBase 是依賴于底層的 distrubuted file system 的三副本的一個(gè) pipeline ,Cockroach DB 、TiDB 等數(shù)據(jù)庫(kù)都是依賴 Paxos 和 Raft 之類的復(fù)制算法來(lái)實(shí)現(xiàn)數(shù)據(jù)的一致性。
          Milvus 2.0 選擇了一條創(chuàng)新道路,依賴 Pub/sub 系統(tǒng)來(lái)做日志的存儲(chǔ)和持久化。Pub/sub 系統(tǒng)是類似 Kafka 或者 Pulsar 的消息隊(duì)列,有這么一套系統(tǒng)后,其他系統(tǒng)的角色就變成了日志的消費(fèi)者。這套系統(tǒng)的存在將日志和服務(wù)器完全解耦,保證 Milvus 本身是沒有狀態(tài)的,這樣可以提升故障恢復(fù)速度。
          除此之外,我們依賴 Kafka 或者 Pulsar 來(lái)做數(shù)據(jù)的可靠性,保證大家的數(shù)據(jù)在使用過(guò)程中是不丟的。Pub/sub 系統(tǒng)的引入可以保證系統(tǒng)的擴(kuò)展性,Milvus 也可以與更多的系統(tǒng)做集成。


          集市架構(gòu)

          有了這套日志系統(tǒng)以后,可以大大簡(jiǎn)化系統(tǒng)的設(shè)計(jì)。我們?cè)趯?Milvus 代碼的時(shí)候,關(guān)注點(diǎn)相對(duì)來(lái)講就會(huì)少一些,保證這個(gè)系統(tǒng)可以快速迭代為大家提供服務(wù)。
          基于這套日志系統(tǒng),我們就設(shè)計(jì)了“集市架構(gòu)”,核心解決的問(wèn)題是如何高效地?cái)U(kuò)展一個(gè)系統(tǒng)。那么“集市架構(gòu)”為什么叫集市呢?它是一種松散的耦合,大家都處在同一個(gè)環(huán)境中,但是每個(gè)人不太關(guān)心彼此在做什么事情。用戶把原始數(shù)據(jù)通過(guò)各種類型的轉(zhuǎn)換,才可以轉(zhuǎn)化成 embedding 數(shù)據(jù),也可以轉(zhuǎn)化成 Semi-structured data。比如說(shuō)一些 text 也可以轉(zhuǎn)化成 Structured data,類似于 relational model。
          通常有兩種插入方式,一種是流式,一種是批式,更對(duì)應(yīng)的是類似 T + 1 的寫入,把它插入到不同的處理引擎里去。比如,向量檢索方面,未來(lái)可能也會(huì)去引入一些第三方的 KV 系統(tǒng)或 text search 系統(tǒng),去做數(shù)據(jù)關(guān)鍵詞檢索,所有數(shù)據(jù)都是從 pub/sub 系統(tǒng)發(fā)給所有訂閱者。
          數(shù)據(jù)寫入之后,還會(huì)有一個(gè)混合查詢的過(guò)程,通過(guò) Query Processor 去完成用戶的查詢,最終把結(jié)果歸并。基于日志系統(tǒng)來(lái)做似乎是一個(gè)比較好的方式,但是也有一些很大的挑戰(zhàn)。最重要的挑戰(zhàn)就是,如果完全基于日志系統(tǒng)回放數(shù)據(jù)來(lái)做查詢的話,查詢本身是比較慢的。按照 TimeTick 把數(shù)據(jù)分成一個(gè)個(gè)窗口,一段窗口的數(shù)據(jù)就會(huì)合并成一個(gè)快照,快照經(jīng)過(guò)一段閾值之后就合并,從而構(gòu)建 vector Index、提高向量搜索效率。除此之外,我們也通過(guò)批量插入的方式去滿足用戶對(duì)離線數(shù)據(jù)的高效處理。
          在讀取路徑中,Milvus 是一個(gè)典型的 MPP(Massively Parallel Processing)架構(gòu)。每個(gè) Segment 搜索是并行進(jìn)行的,Proxy 聚合 Top-K 結(jié)果并返回客戶端。


            Milvus 2.0 概覽與模塊劃分

          Milvus 單機(jī)與分布式

          Milvus 目前來(lái)講提供兩種部署方式,一種是單機(jī)版,所有節(jié)點(diǎn)部署在一起,也就是說(shuō) Milvus 本身就是一個(gè)進(jìn)程。目前單機(jī)版依賴 Etcd,也依賴 MinIO 。在后續(xù)版本中,去掉 MinIO 和 etcd,保證單機(jī)版足夠簡(jiǎn)單,可以讓大家能夠把 Milvus 用起來(lái)。
          另一種是分布式,這個(gè)方案相對(duì)來(lái)講比較復(fù)雜,符合微服務(wù)化的設(shè)計(jì)。那么它依賴的除了 etcd 和 MinIO,還有就是 Pulsar。Pulsar 作為我們整個(gè)系統(tǒng)的 log broker 來(lái)實(shí)現(xiàn)以日志為主干的設(shè)計(jì)。


          Milvus 的角色

          具體到所有角色來(lái)看,整個(gè) Milvus 的分布式方案有八個(gè)角色和三個(gè)不同的依賴。
          這八個(gè)角色中,上面四個(gè)的 Coordinator 部分也叫 Coordinator Service ,下方分四種 Worker Node,每個(gè) Worker Node 類似于 Hadoop 里的 Data Node 或者 HBase 里的 Region Server。橫向來(lái)看,它用于執(zhí)行用戶請(qǐng)求,區(qū)分種類是為了管控節(jié)點(diǎn)和下方的 Worker 節(jié)點(diǎn)??v向來(lái)看,Query Coord 對(duì)應(yīng) Query Node ,Data Coord 對(duì)應(yīng) Data Node,Index Coord 對(duì)應(yīng) Index Node,Root Coord 對(duì)應(yīng) Proxy Node。
          每種角色到底有什么作用呢?
          從最前端講起, Proxy 就是充當(dāng)系統(tǒng)門面,所有的 SDK 查詢都會(huì)通過(guò)一個(gè) load balancer,發(fā)給 Pulsar Proxy 去處理連接,做一些靜態(tài)檢查。比如,一個(gè)請(qǐng)求,可能 collection 名字根本不存在,Pulsar Proxy 就會(huì)直接報(bào)錯(cuò),或者當(dāng)插入的數(shù)據(jù)缺少了某些列,就會(huì)由 SDK 發(fā)現(xiàn)。完成了預(yù)處理之后, Proxy 就會(huì)把數(shù)據(jù)投遞到 Message Broker 里。
          整體來(lái)講,Proxy 會(huì)處理三類數(shù)據(jù):寫請(qǐng)求、讀請(qǐng)求、控制請(qǐng)求,比如 DDL。Proxy 需要把數(shù)據(jù)投遞到對(duì)應(yīng)的 channel 里, Root Coord 類似于傳統(tǒng)系統(tǒng)中的 Master,主要做一些 DDL 和 DCL 的管理,比如建 Collection、刪 Collection。
          除此之外,Root Coord 還承擔(dān)著非常大的責(zé)任,就是為系統(tǒng)分配時(shí)間戳。TimeTick 的機(jī)制會(huì)保證數(shù)據(jù)根據(jù)時(shí)間戳定序。
          很多朋友可能會(huì)擔(dān)心,是不是會(huì)有單點(diǎn)的存在?對(duì)于 Milvus 而言,第一,性能瓶頸這塊是比較好處理的,不太需要去做過(guò)多考慮,寫入往往都是批量插入的,所以 TPS 本身沒有那么高,只要滿足吞吐的要求即可。第二,Milvus 在讀鏈路的時(shí)候,對(duì)中心授權(quán)模塊沒有過(guò)多的依賴,因此 Root Coord 節(jié)點(diǎn)宕機(jī)不會(huì)對(duì)整個(gè)系統(tǒng)的讀入有任何影響。第三,Milvus 依賴云原生的設(shè)計(jì),Root Coord 如果宕機(jī),可以快速被 Kubernetes 拉起來(lái),可用性有保障。
          Data 有兩種角色,Data Coord 和 Data node。Data Coord 是協(xié)調(diào)者,會(huì)做一些 load balance 的分配、管理 segment、處理 Data Node 故障的恢復(fù),比如有些 Data Node 宕機(jī)的話,是通過(guò) Data Coord 發(fā)現(xiàn)和恢復(fù)的。Data Node 就做一件事情,把 log 里面的數(shù)據(jù)轉(zhuǎn)化成 log snapshot,log snapshot 可以理解為 binlog,會(huì)生成一塊大的 binlog,每個(gè) binlog 通過(guò) parquet 的格式存。Data Node 生成文件后,就會(huì)把文件傳給 Index Node、生成 Sealed Segment,然后 Index Coord 會(huì)對(duì) Sealed Segment 建索引。
          有的同學(xué)會(huì)好奇,為什么建索引還要抽單獨(dú)的角色去做,直接加一塊做完可不可以?其實(shí)也是可以的。但是抽單獨(dú)的角色去做的好處在于,第一, Index  很消耗性能,對(duì)彈性的要求更高。它不需要長(zhǎng)時(shí)間保存的內(nèi)存,如果有見縫插針的資源,Index 就可以用起來(lái)。第二, Index 本身很消耗資源,所以通常情況下用戶做一些異構(gòu)加速,Index Node 可以用 GPU 或?qū)S糜布?duì)索引做加速。Index Node 生成數(shù)據(jù)之后,就會(huì)把數(shù)據(jù)給到 Query Node 管理。所有的 Segment 都在 Query Node 上提供服務(wù),通過(guò) Query Node 執(zhí)行查詢。Query Node 有很多除了故障恢復(fù)以外的查詢邏輯,同時(shí)也是整個(gè) Milvus 里最復(fù)雜的節(jié)點(diǎn)。


          Milvus 架構(gòu)概覽

          整個(gè)系統(tǒng)的框圖如下。從左側(cè)來(lái)看,SDK 把數(shù)據(jù)發(fā)到 Load Balancer,進(jìn)入 Proxy,再根據(jù)不同的查詢寫入 Log Broker 里來(lái),最后由 Log Broker 通知 Data Node 新增的數(shù)據(jù)。
          這里有個(gè)比較有意思的地方:新增數(shù)據(jù)除了要進(jìn) Data Node 之外,也會(huì)進(jìn) Query Node。有些用戶對(duì)數(shù)據(jù)的實(shí)時(shí)性有比較高的要求,因此會(huì)通過(guò) Broker 提前通知 Query Node 有新增數(shù)據(jù),保證數(shù)據(jù)的可見周期更短。當(dāng)然所有查詢也會(huì)通過(guò) Log Broker 發(fā)到 Query Node 上,Query Node 執(zhí)行完以后再把結(jié)果傳回到 Log Broker,通知 Proxy。
          在 Query Node、Data Node 和 Index Node 之下,是基于 S3 構(gòu)建的云存儲(chǔ)。我們發(fā)現(xiàn)云存儲(chǔ)本身有很高的可能性,成本也比較低,非常適合 Milvus 存儲(chǔ)持久化的數(shù)據(jù)。
          在 Coordinator Service 部分,除了剛剛說(shuō)的 Root、Query、Data、Index 以外,還有 Meta Storage,目前是用 etcd 做的。一些比較小的 etcd 不太適合存在 S3 上,所以我們把這些數(shù)據(jù)存在 etcd 上,etcd 也提供了很好的事務(wù)能力,整個(gè)系統(tǒng)的故障恢復(fù)和服務(wù)發(fā)現(xiàn)也是基于 etcd 去做的。


          Milvus 的數(shù)據(jù)模型

          那么 Milvus 到底提供給用戶什么樣的數(shù)據(jù)模型或能力呢?
          首先,我們?yōu)橛脩籼峁┑淖畲蟾拍罱凶?Collection,即可以映射到傳統(tǒng)數(shù)據(jù)庫(kù)的一個(gè)表。每個(gè) Collection 我們會(huì)分多個(gè) Shard,默認(rèn)情況下是兩個(gè) Shard,到底要取多少 Shard 取決于你的寫入量有多大、需要把寫入分到多少個(gè)節(jié)點(diǎn)去做處理。如果你的寫入比較少,默認(rèn)兩個(gè) Shard 就可以滿足你的需求。
          如果你的集群規(guī)模是 10 臺(tái)或 100 臺(tái),我們推薦 Shard 的規(guī)模做到 Data Node 的兩到三倍。每個(gè) Shard 中間又有很多 Partition ,Partition 自帶數(shù)據(jù)的屬性, Shard 本身是根據(jù)主鍵的哈希去分的,而 Partition 往往是根據(jù)你指定的字段或 Partition 的 tag 去分的。常見的 Partition 方式有根據(jù)數(shù)據(jù)寫入的日期劃分、根據(jù)用戶是男女去劃分、根據(jù)用戶的年齡去劃分等。Partition 的一個(gè)很大優(yōu)勢(shì)是在查詢過(guò)程中,如果你加上 Partition tag 的話,可以幫你過(guò)濾掉很多數(shù)據(jù)。
          Shard 更多是幫你去擴(kuò)展寫的操作,而 Partition 是幫你在讀操作的情況下去提升讀的一個(gè)性能,每個(gè) Shard 里的每個(gè) partition 又會(huì)對(duì)應(yīng)到很多小的 Segment 。Segment 就是我們整個(gè)系統(tǒng)調(diào)度的最小單元,分為 Growing Segment 和 Sealed Segment。Growing Segment 就是 Query Node 訂閱,用戶持續(xù)寫入 Segment,等 Growing Segment 寫大了以后,就不允許繼續(xù);默認(rèn)上限是 512MB,寫到上限以后,我們就把它 seal 掉,并對(duì) seal 的 Segment 建一些向量索引。
          在讀的時(shí)候,Growing Segment 和 Sealed Segment 都是需要去被讀到的,可以保證用戶數(shù)據(jù)的可見實(shí)時(shí)性比較高。每個(gè) Segment 里又分為很多 Entitity,Entity 是傳統(tǒng)數(shù)據(jù)庫(kù)里面“一行”的概念。Entity 是有 Schema 的,通常一個(gè) Entitity 中必須有一個(gè) Primary Key。一般來(lái)講,我們會(huì)有一個(gè)隱式的 ts 字段,Primary Key 如果不是主動(dòng)指定的話,往往可以自增。除此之外,還有一個(gè)列和 Vector,一個(gè) Entitity 會(huì)有一個(gè) Vector, Vector 也是整個(gè) Milvus 系統(tǒng)的核心。


          Milvus 數(shù)據(jù)存儲(chǔ)模式

          Milvus 在存儲(chǔ)數(shù)據(jù)的過(guò)程中,會(huì)把數(shù)據(jù)存成什么樣?
          首先,存儲(chǔ)過(guò)程是以 Segment 為單位,用的是列存的方式,每個(gè) Primary Key 、Column、Vector 都是單獨(dú)用一個(gè)文件存儲(chǔ)。Segment seal 掉之后,我們會(huì)針對(duì)性地構(gòu)建 Vector Index,整個(gè) segment 只構(gòu)建一個(gè)。
          Vector Index 目前來(lái)講只能支持建一個(gè)索引,我們很快就會(huì)支持一個(gè)表建多個(gè)索引。比如你想嘗試 HNSW 和 IVF-PQ 到底哪個(gè)性能好的話,可以建多個(gè)索引。后續(xù)我們可能還會(huì)再加入一些自動(dòng)調(diào)優(yōu)的部分,幫用戶自動(dòng)選擇建一些索引。
          為什么要選擇存儲(chǔ)的過(guò)程中去列存呢?第一,列存的壓縮率比較高,通常我們都是存一些 int 型的數(shù)據(jù),或者存一些稠密的 float int 向量,可以通過(guò)列存去做比較好的壓縮。第二,做標(biāo)量過(guò)濾可能會(huì)通過(guò)回盤的方式去做讀取,那么列式存儲(chǔ)可以用來(lái)做加速。
          Sealed Segment 一旦寫入完成,就不能修改。實(shí)際過(guò)程中,用戶會(huì)有刪除或者修改數(shù)據(jù)的需求,因此我們就在 Segment 加了 Delta Log,每個(gè) Delta Log 包含了幾行刪除或追加的數(shù)據(jù)。
          用戶做刪除的時(shí)候,我們會(huì)通過(guò)路由找到對(duì)應(yīng)的 Segment,在 Segment 里面生成 Delta Log。Delta Log 有點(diǎn)類似于傳統(tǒng)的 LSM 樹的架構(gòu),我們會(huì)先去讀原始文件,然后把 Delta Log 根據(jù)時(shí)間戳慢慢打到讀出來(lái)的數(shù)據(jù)上。如果 Delta Log 的 ts 大于原始數(shù)據(jù)的 ts,那么原始數(shù)據(jù)就會(huì)被刪除。Delta Log 寫多了或者刪除多了之后,也需要做清理,不然你的讀取就會(huì)變得越來(lái)越慢。因此我們基于文件格式做 compaction ,定時(shí)把 Delta Log 整合到原有的文件里面,使得在讀的過(guò)程中保證不需要往回打太多的數(shù)據(jù)。


            Milvus 代碼閱讀注意事項(xiàng)

          準(zhǔn)備工作

          在你真正了解 Milvus 之前,你可以做如下準(zhǔn)備工作:
          第一,Milvus 本身是基于 Go 和 C++ 來(lái)寫的,上層的分布式用的是 Go,下層的核心部分用的是 C++。Go 的部分幫助我們更加的云原生,以及幫助系統(tǒng)更好地去做拓展。C++ 的部分更多是出于性能和異構(gòu)硬件的考慮。所以你需要對(duì)這兩種語(yǔ)言都有一定的了解,我們建議初學(xué)者先從 Go 來(lái)入手。
          第二,閱讀 Milvus 官網(wǎng)上關(guān)于系統(tǒng)架構(gòu)的設(shè)計(jì)文檔(https://milvus.io/docs/architecture_overview.md)。今天講的內(nèi)容很大程度上都會(huì)在覆蓋這個(gè)文檔里,未來(lái)我們也會(huì)補(bǔ)充各種各樣的設(shè)計(jì)文檔到 Milvus 官網(wǎng)和我們的 GitHub 里面。
          第三,Milvus 本身依賴 Pulsar、etcd、開源的 MinIO、S3 等。因此,在讀 Milvus 代碼之前,你可以先了解一下這些東西在做什么。你還可以閱讀我們?cè)?SIGMOD 2021 發(fā)表的 paper,你會(huì)對(duì) Milvus 這個(gè)系統(tǒng)的初心以及它的一些用途有更深入的了解。
          Milvus: A Purpose-Built Vector Data Management System, SIGMOD'21
          地址:https://www.cs.purdue.edu/homes/csjgwang/pubs/SIGMOD21_Milvus.pdf
          最后,你要先完成 Milvus 的 study demo,了解一下 Milvus 到底能幫你做哪些事情。在你開始去熟悉一個(gè)系統(tǒng)之前,先成為他的用戶,簡(jiǎn)單地把這個(gè)東西玩一玩。
          Demo 地址:https://milvus.io/milvus-demos


          學(xué)習(xí)路徑

          當(dāng)你做完這些事情以后,接下來(lái)的學(xué)習(xí)內(nèi)容可以參考如下路徑:
          第一,Milvus 的一些 API 和 Python SDK 的實(shí)現(xiàn)
          第二 ,了解系統(tǒng)前端的設(shè)計(jì)、proxy 的功能,以及 Milvus 的增刪改查等主要操作的路徑和流程
          第三,數(shù)據(jù)文件的生成路徑,以及存儲(chǔ)的格式
          第四,查詢路徑(數(shù)據(jù)查詢進(jìn)入到 Milvus 之后會(huì)經(jīng)歷哪些組件,每個(gè)組件大概實(shí)現(xiàn)一些什么樣的功能)、故障恢復(fù)、負(fù)載均衡
          最后,學(xué)習(xí)標(biāo)量執(zhí)行引擎,和向量執(zhí)行
          DeepDive 系列也將按照以上路徑為大家進(jìn)行講解。


          等我熟悉了 Milvus,我可以……

          熟悉了代碼之后你應(yīng)該做什么呢?
          首先,歡迎大家加入 Contributer 大家庭,希望大家可以花點(diǎn)時(shí)間閱讀我們的文檔,甚至參與修改我們的文檔。文檔地址:https://milvus.io/docs
          當(dāng)你熟悉的這個(gè)系統(tǒng)之后,我相信你會(huì)有很多的 idea ,也許你想了解更多的技術(shù)細(xì)節(jié)以及這個(gè)社區(qū)想要發(fā)展的方向。我們的 Tech Meeting 會(huì)定期同步到 LF AI & Data 的 Home (地址:https://wiki.lfaidata.foundation/display/MIL/Milvus+Home)。歡迎大家加入我們的討論!
          想要第一時(shí)間了解了解社區(qū)最新的功能和改進(jìn)?
          GitHub: https://github.com/milvus-io/milvus
          歡迎在這里與我們暢聊新功能!
          Slack: https://milvusio.slack.com/
          當(dāng)然最重要的就是為  Milvus 社區(qū)貢獻(xiàn)代碼,你貢獻(xiàn)的代碼是可以讓全世界的工程師都看到都用起來(lái),這也是大家為什么都非常愿意加入到  Milvus 社區(qū)的重要原因,用我們自己的力量去幫助更多的人去使用。當(dāng)你對(duì)這個(gè)代碼有很深入的理解以后,歡迎你在知乎或者在一些其他地方分享關(guān)于 Milvus 代碼學(xué)習(xí)的一些心得體會(huì),讓更多的人能方便學(xué)習(xí)和使用 Milvus!




          Zilliz 數(shù)據(jù)學(xué),領(lǐng)術(shù)創(chuàng),過(guò)業(yè)結(jié)構(gòu)數(shù)據(jù)價(jià)。
          Zilliz 構(gòu) Milvus 數(shù)據(jù)庫(kù),數(shù)據(jù)臺(tái)發(fā)。Milvus 數(shù)據(jù)庫(kù) LF AI & Data 會(huì)業(yè)項(xiàng),結(jié)構(gòu)數(shù)據(jù),發(fā)現(xiàn)、統(tǒng)、機(jī)應(yīng)用。

          閱讀原文,解鎖更多應(yīng)用場(chǎng)景

          瀏覽 411
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产乱妇交换做爰XXXⅩ麻豆 | 一区二区三区在线 | 国产做受 91电影 | 免费 无码 国产真人视频 | 一区二区三区无马亚 |