精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

得物向量數(shù)據(jù)庫(kù)落地實(shí)踐

開(kāi)發(fā) 前端
信息通信技術(shù)(ICT)正經(jīng)歷著前所未有的變革浪潮,以大模型和生成式人工智能(GenAI)為代表的技術(shù)突破,正在引發(fā)全球產(chǎn)業(yè)體系的深刻變革,成為驅(qū)動(dòng)企業(yè)技術(shù)架構(gòu)革新和商業(yè)模式轉(zhuǎn)型的關(guān)鍵引擎。

一、背景

二、認(rèn)識(shí)向量數(shù)據(jù)庫(kù)

    1. 向量數(shù)據(jù)來(lái)源和存儲(chǔ)

    2. 向量數(shù)據(jù)庫(kù)是如何工作

三、向量數(shù)據(jù)庫(kù)對(duì)比傳統(tǒng)數(shù)據(jù)庫(kù)

四、如何選擇向量數(shù)據(jù)庫(kù)

    1. 向量數(shù)據(jù)庫(kù)比較

    2. 選擇流行的索引

    3. 綜合比較和選擇

    4. 得物選擇Milvus作為向量數(shù)據(jù)庫(kù)

五、Milvus在得物的實(shí)踐

    1. 部署架構(gòu)演進(jìn)

    2. 獨(dú)立資源池遷移至共享資源池

    3. 引入Zilliz

六、向量數(shù)據(jù)庫(kù)運(yùn)維沉淀

    1. 索引結(jié)構(gòu)和搜索原理

    2. 并不是你想的那樣

    3. 錯(cuò)誤處理

七、未來(lái)展望

一、背景

信息通信技術(shù)(ICT)正經(jīng)歷著前所未有的變革浪潮,以大模型和生成式人工智能(GenAI)為代表的技術(shù)突破,正在引發(fā)全球產(chǎn)業(yè)體系的深刻變革,成為驅(qū)動(dòng)企業(yè)技術(shù)架構(gòu)革新和商業(yè)模式轉(zhuǎn)型的關(guān)鍵引擎。

得物是廣受年輕人喜愛(ài)的品質(zhì)生活購(gòu)物社區(qū)。在AI鑒別、圖搜、算法、安全風(fēng)控等場(chǎng)景下都廣泛使用啦GenAI技術(shù)。

向量數(shù)據(jù)庫(kù)作為GenAI的基礎(chǔ)設(shè)施之一,通過(guò)量化的高維空間數(shù)據(jù)結(jié)構(gòu)(如HNSW算法),實(shí)現(xiàn)對(duì)嵌入向量(Embeddings Vector)的高效存儲(chǔ)、索引和最近鄰搜索(ANN),支撐包括多模態(tài)數(shù)據(jù)表征在內(nèi)的復(fù)雜智能應(yīng)用。

二、認(rèn)識(shí)向量數(shù)據(jù)庫(kù)

向量數(shù)據(jù)來(lái)源和存儲(chǔ)

圖片圖片

一般向量數(shù)據(jù)庫(kù)中向量的來(lái)源是將圖片、音頻、視頻、文本等非結(jié)構(gòu)化數(shù)據(jù),將這些非結(jié)構(gòu)化數(shù)據(jù)通過(guò)對(duì)應(yīng)的量化算法計(jì)算出一個(gè)多維度的向量(生產(chǎn)使用一般向量維度會(huì)大于512),并且將向量數(shù)據(jù)持久化在特定的存儲(chǔ)上。

向量數(shù)據(jù)庫(kù)是如何工作

圖片圖片

向量數(shù)據(jù)庫(kù)在查詢(xún)的時(shí)候一般會(huì)將需要查詢(xún)的非結(jié)構(gòu)化數(shù)據(jù)通過(guò)量化,計(jì)算成一個(gè)多維度向量數(shù)據(jù),然后在數(shù)據(jù)庫(kù)中搜索出和查詢(xún)向量相似的數(shù)據(jù)。(需要注意的是這邊查詢(xún)的是相似的數(shù)據(jù)而不是相同的數(shù)據(jù))。

三、向量數(shù)據(jù)庫(kù)對(duì)比傳統(tǒng)數(shù)據(jù)庫(kù)

圖片圖片

圖片圖片

向量數(shù)據(jù)庫(kù)在數(shù)據(jù)結(jié)構(gòu)、檢索方法、擅長(zhǎng)領(lǐng)域與傳統(tǒng)數(shù)據(jù)庫(kù)有很大的不同。

傳統(tǒng)數(shù)據(jù)庫(kù)

結(jié)構(gòu)是處理離散的標(biāo)量數(shù)據(jù)類(lèi)型(例如數(shù)字和字符串),并通過(guò)行和列來(lái)表達(dá)組織數(shù)據(jù)(就是一個(gè)表格)。傳統(tǒng)數(shù)據(jù)庫(kù)主要為了解決結(jié)構(gòu)化數(shù)據(jù)的精確管理和高效查詢(xún)問(wèn)題。并且傳統(tǒng)數(shù)據(jù)庫(kù)通過(guò)B樹(shù)索引、哈希索引等數(shù)據(jù)結(jié)構(gòu),能夠快速定位到精確匹配的記錄。更重要的是,傳統(tǒng)數(shù)據(jù)庫(kù)通過(guò)ACID事務(wù)特性(原子性、一致性、隔離性、持久性)確保了在數(shù)據(jù)中數(shù)據(jù)的絕對(duì)準(zhǔn)確性。

向量數(shù)據(jù)庫(kù)

為了解決非結(jié)構(gòu)化數(shù)據(jù)的語(yǔ)義搜索問(wèn)題,解決如何在海量的高維向量數(shù)據(jù)中,快速找到與查詢(xún)向量最相似的結(jié)果。比如在推薦系統(tǒng)中找到與用戶(hù)喜好相似的物品,或在圖像庫(kù)中檢索出與查詢(xún)圖片最相近的圖片。這類(lèi)問(wèn)題的特點(diǎn)是:

  1. 查詢(xún)的不是精確匹配,而是相似度排名。
  2. 數(shù)據(jù)維度極高(通常128-2048維)。
  3. 數(shù)據(jù)規(guī)模龐大(可能達(dá)到十億級(jí)別)。

傳統(tǒng)數(shù)據(jù)庫(kù)的精確查詢(xún)方式在這種場(chǎng)景下完全失效,因?yàn)椋?/p>

  1. 無(wú)法為高維向量建立有效的B樹(shù)索引。
  2. 計(jì)算全量數(shù)據(jù)的精確相似度代價(jià)過(guò)高。
  3. 無(wú)法支持"相似但不完全相同"的搜索需求。

四、如何選擇向量數(shù)據(jù)庫(kù)

向量數(shù)據(jù)庫(kù)比較

下面我們通過(guò)10個(gè)不同維度來(lái)比較一下不同向量數(shù)據(jù)庫(kù)的區(qū)別:

圖片圖片

從上面表格可以看到:

  1. 自 2016 年起 ,向量數(shù)據(jù)庫(kù)逐漸嶄露頭角,成為 AI 和大數(shù)據(jù)領(lǐng)域的重要基礎(chǔ)設(shè)施。而到了 2021 年之后 ,隨著深度學(xué)習(xí)、大模型和推薦系統(tǒng)的迅猛發(fā)展,向量數(shù)據(jù)庫(kù)正式邁入爆發(fā)式增長(zhǎng)時(shí)代 ,成為現(xiàn)代數(shù)據(jù)架構(gòu)中不可或缺的核心組件。
  2. 超過(guò)半數(shù)的向量數(shù)據(jù)庫(kù)均采用分布式架構(gòu)設(shè)計(jì),并且這些支持分布式部署的系統(tǒng)普遍具備彈性擴(kuò)縮容能力,能夠根據(jù)業(yè)務(wù)需求實(shí)現(xiàn)資源的動(dòng)態(tài)調(diào)整。
  3. 當(dāng)業(yè)務(wù)需要處理億級(jí)甚至更高規(guī)模的向量數(shù)據(jù)時(shí),推薦以下高性能、可擴(kuò)展的向量數(shù)據(jù)庫(kù):Vespa、Milvus/Zilliz、Vald、Qdrant。
  4. 當(dāng)前主流的向量數(shù)據(jù)庫(kù)普遍采用模塊化、插件式的設(shè)計(jì)理念。其核心引擎大多基于 C/C++ 開(kāi)發(fā),以追求極致的性能表現(xiàn)。與此同時(shí),Go 和 Rust 也正在這一領(lǐng)域嶄露頭角。
  5. 在向量數(shù)據(jù)庫(kù)領(lǐng)域,NHSW(Hierarchical Navigable Small-World)和 DiskANN 正逐漸成為主流索引方案。其中NHSW主要以?xún)?nèi)存搜索為主,DiskANN主要以磁盤(pán)搜索為主。值得注意的是,Qdrant 在優(yōu)化 NHSW 的基礎(chǔ)上,進(jìn)一步實(shí)現(xiàn)了 基于磁盤(pán)的 NHSW 檢索能力。

選擇流行的索引

在向量數(shù)據(jù)庫(kù)技術(shù)領(lǐng)域,有NHSW 和 DiskANN 作為兩大主流索引方案,各自展現(xiàn)了獨(dú)特的技術(shù)優(yōu)勢(shì)。我們從以下關(guān)鍵維度進(jìn)行專(zhuān)業(yè)對(duì)比分析。

圖片圖片

從上表格我們可以得到,NHSW和DiskANN適用于不同的場(chǎng)景:

  • NHSW :以 內(nèi)存優(yōu)先 的設(shè)計(jì)實(shí)現(xiàn)高性能搜索,適合對(duì) 低延遲、高吞吐 要求嚴(yán)格的場(chǎng)景,如實(shí)時(shí)推薦、廣告檢索等。
  • DiskANN :以 磁盤(pán)存儲(chǔ)優(yōu)化 為核心,在保證較高召回率的同時(shí) 顯著降低硬件成本 ,適用于大規(guī)模數(shù)據(jù)下的經(jīng)濟(jì)型檢索需求。

隨著數(shù)據(jù)規(guī)模的持續(xù)增長(zhǎng),NHSW 和 DiskANN 的混合部署模式 或?qū)⒊蔀樾袠I(yè)標(biāo)準(zhǔn),讓用戶(hù)能根據(jù)業(yè)務(wù)需求靈活選擇 "極致性能" 或 "最優(yōu)成本" 的檢索策略。

綜合比較和選擇

圖片圖片

從表格中可以得到:

  1. 如果數(shù)據(jù)流比較小,并且自身對(duì)Redis、PG、ES比較熟悉,就可以選擇Redis、PG、ES。如DBA團(tuán)隊(duì)就比較適合。
  2. 如果數(shù)據(jù)量比較大,并且前期人力不足可以使用云托管方案。選擇Zilliz、Pinecone、Vespa或者Qdrant,如果后期計(jì)劃從云上遷移到自建可以選擇Zilliz、Vespa或者Qdrant。

得物選擇Milvus作為向量數(shù)據(jù)庫(kù)

我們的需求

社區(qū)圖搜和AI鑒別需要大量的數(shù)據(jù)支持,得物業(yè)務(wù)場(chǎng)景要求能支持十億級(jí)向量數(shù)據(jù)搜索,有如下要求:

  1. 大數(shù)據(jù)量高性能搜索,RT需要在90ms以?xún)?nèi)。
  2. 大數(shù)據(jù)量但是性能要求不高時(shí),RT滿(mǎn)足500ms以?xún)?nèi)。

需要支持快速擴(kuò)縮容:

滿(mǎn)足上面2點(diǎn)就已經(jīng)鎖定在Milvus、Qdrant這兩個(gè)向量數(shù)據(jù)庫(kù)。如果從架構(gòu)復(fù)雜度和維護(hù)/學(xué)習(xí)成本的角度考慮,我們應(yīng)該優(yōu)先選擇Qdrant,因?yàn)樗募軜?gòu)相比Milvus沒(méi)有那么復(fù)雜,并且維護(hù)/學(xué)習(xí)成本沒(méi)有Milvus高,重要的Qdrant可以單獨(dú)集群部署,不需要k8s技術(shù)棧的支撐。

Milvus 和 Qdrant 架構(gòu)比較

Milvus架構(gòu)

Milvus部署依賴(lài)許多外部組件,如存儲(chǔ)元信息的ETCD、存儲(chǔ)使用的MinIO、消息存儲(chǔ)Pulasr 等等。

圖片圖片

Qdrant

Qdrant完全獨(dú)立開(kāi)發(fā),支持集群部署,不需要借助ETCD、Pulsar等組件。

圖片

選擇Milvus的原因

※ 業(yè)務(wù)發(fā)展需求

業(yè)務(wù)屬于快速發(fā)展階段,數(shù)量的變化導(dǎo)致擴(kuò)縮容頻繁,使用支持k8s的Milvus在擴(kuò)縮容方面會(huì)比Qdrant快的多。

※ 技術(shù)儲(chǔ)備和社區(qū)良好

對(duì)DBA而言,向量數(shù)據(jù)庫(kù)領(lǐng)域需要持續(xù)的知識(shí)更新和技術(shù)支持。從問(wèn)題解決效率來(lái)看,國(guó)內(nèi)技術(shù)社區(qū)對(duì)Milvus的支持體系相較于Qdrant更為完善。

※ 契合得物DBA開(kāi)發(fā)棧

Milvus使用的開(kāi)發(fā)語(yǔ)言是Go,契合DBA團(tuán)隊(duì)技術(shù)棧,在部分運(yùn)維場(chǎng)景下情,通過(guò)二次開(kāi)發(fā)滿(mǎn)足運(yùn)維需求。例如:使用milvus-backup工具做遷移,部分的segment有問(wèn)題需要跳過(guò)。自行修改一下代碼編譯運(yùn)行即可滿(mǎn)足需求。

圖片圖片

五、Milvus在得物的實(shí)踐

部署架構(gòu)演進(jìn)

小試牛刀

初始階段,我們把Milvus部署在K8S上,默認(rèn)使用HNSW索引。架構(gòu)圖如下,Milvus整個(gè)架構(gòu)較為復(fù)雜,外部依賴(lài)的組件多,每個(gè)集群需要部署自己的 ETCD、ZK、消息隊(duì)列模塊,多套集群共享著同一個(gè)存儲(chǔ)。

圖片圖片

存儲(chǔ)拆分,每個(gè)集群獨(dú)立存儲(chǔ)

共享存儲(chǔ)瓶頸導(dǎo)致穩(wěn)定性問(wèn)題凸顯。

隨著業(yè)務(wù)規(guī)模擴(kuò)展,集群數(shù)量呈指數(shù)級(jí)增長(zhǎng),我們觀測(cè)到部分集群節(jié)點(diǎn)出現(xiàn)異常重啟現(xiàn)象,經(jīng)診斷確認(rèn)該問(wèn)題源于底層共享存儲(chǔ)存在性能瓶頸。

圖片圖片

圖片圖片

獨(dú)立資源池遷移至共享資源池

通過(guò)混布的方式提升資源利用率。

前期為了在性能和穩(wěn)定性上更好的服務(wù)業(yè)務(wù),Milvus部署的底層機(jī)器都是獨(dú)立的,目的就是為了和其他應(yīng)用隔離開(kāi),不相互影響。但是隨著集群的越來(lái)越多,并不是所有的集群對(duì)穩(wěn)定性和性能要求那么高,從監(jiān)控上看Milvus集群池的資源使用不超過(guò)10%。為了提高公司資源利用率,我們將獨(dú)立部署的Milvus遷移高共享資源池中,和大數(shù)據(jù)、業(yè)務(wù)應(yīng)用等K8S部署相關(guān)服務(wù)進(jìn)行混合部署。

圖片圖片

DiskANN索引的使用

數(shù)據(jù)量大且搜索QPS小時(shí)選擇DiskANN 作為索引。通過(guò)監(jiān)控發(fā)現(xiàn)有很多集群數(shù)據(jù)量比較大,但是QPS并不是那么高,這時(shí)候就考慮對(duì)這些性能要求不高的集群是否有降本的方案。通過(guò)了解我們默認(rèn)使用的HNSW索引需要將所有數(shù)據(jù)都加載到內(nèi)存中進(jìn)行搜索,第一反應(yīng)就是它的內(nèi)存查詢(xún)和Redis一樣,那是否有類(lèi)似pika的方案內(nèi)存只存少部分?jǐn)?shù)據(jù)大部分?jǐn)?shù)據(jù)存在磁盤(pán)上。這時(shí)候發(fā)現(xiàn)DiskANN就能達(dá)到這樣的效果。

性能壓測(cè)

※ 集群規(guī)格

圖片圖片

QPSQPS

延時(shí)(ms)延時(shí)(ms)


新增DiskANN索引后集群架構(gòu)

增加DiskANN后我們需要對(duì)相關(guān)服務(wù)器上掛載 NVME SSD 磁盤(pán),用于在磁盤(pán)上搜索最終數(shù)據(jù)。

圖片

DiskANN 加載數(shù)據(jù)過(guò)程

圖片圖片

引入Zilliz

經(jīng)過(guò)大規(guī)模生產(chǎn)驗(yàn)證,Milvus在實(shí)際業(yè)務(wù)場(chǎng)景中展現(xiàn)出卓越的性能表現(xiàn)和穩(wěn)定性,獲得業(yè)務(wù)方的高度認(rèn)可。并且也吸引來(lái)了C端核心業(yè)務(wù)系統(tǒng)的使用。在使用前,我們使用了業(yè)務(wù)真實(shí)流量充分的對(duì)Milvus進(jìn)行了壓測(cè),發(fā)現(xiàn)Milvus在億級(jí)別數(shù)據(jù)量的情況下滿(mǎn)足不了業(yè)務(wù),因此對(duì)于部分核心場(chǎng)景我們使用了Zilliz。

Milvus和Zilliz 壓測(cè)

業(yè)務(wù)的要求是集群返回的RT不能操過(guò)90ms。

使用真實(shí)的業(yè)務(wù)數(shù)據(jù)(億級(jí)別)和業(yè)務(wù)請(qǐng)求對(duì)Milvus進(jìn)行壓測(cè),發(fā)現(xiàn)Milvus并不能滿(mǎn)足業(yè)務(wù)的需求。



類(lèi)型





QPS





平均RT(ms)





客戶(hù)端性能圖





Milvus





110





200




圖片




zilliz






350





65




圖片


Milvus RT 200不滿(mǎn)足業(yè)務(wù)需求,并且QPS一直上不去,無(wú)論我們對(duì)QueryNode擴(kuò)容多大,其中還發(fā)生過(guò),將Query擴(kuò)容到60個(gè)后,反而RT上升的問(wèn)題,排查后是因?yàn)橛械腝ueryNode和Proxy交互的時(shí)候網(wǎng)絡(luò)會(huì)抖動(dòng)影響了整體的RT。

從上面可以看出就算業(yè)務(wù)能容忍RT=200ms的,Milvus也需要?jiǎng)?chuàng)建3個(gè)相同的集群提供業(yè)務(wù)訪問(wèn),并且業(yè)務(wù)需要改造代碼實(shí)現(xiàn)多寫(xiě)、多讀的功能,最終還會(huì)發(fā)現(xiàn)3個(gè)集群的成本遠(yuǎn)高于Zilliz。

通過(guò)成本和性能上的考慮,對(duì)于大數(shù)據(jù)量并且性能和穩(wěn)定性要求高場(chǎng)景,我們將選用Zilliz。

遷移方案

對(duì)于不同業(yè)務(wù)場(chǎng)景,我們分別制定了以下3種遷移方案:

方案1:業(yè)務(wù)自行導(dǎo)入數(shù)據(jù)使用

圖片

方案2:備份恢復(fù) + 業(yè)務(wù)增量

圖片

方案3:全量 + 增量 + 業(yè)務(wù)雙寫(xiě)/回滾

圖片

高可用架構(gòu)部署

隨著業(yè)務(wù)關(guān)鍵性持續(xù)提升,Milvus對(duì)應(yīng)的SLA變得越來(lái)越重要。在此背景下,構(gòu)建完善的Milvus高可用架構(gòu)與災(zāi)備體系已成為系統(tǒng)設(shè)計(jì)的核心考量要素。比如:主從、多zone部署,Proxy高可用,Minio高可用,一個(gè)zone完全掛了怎么辦等問(wèn)題?

方案1: 同城多機(jī)房混部

正常訪問(wèn):

  • 該方案會(huì)有客戶(hù)端會(huì)有跨機(jī)房訪問(wèn)的情況。

跨機(jī)房訪問(wèn)節(jié)點(diǎn):

客戶(hù)端 -> SLB

SLB -> Proxy

Proxy -> QueryNode

  • SLB有高可用
  • Proxy有高可用

圖片圖片

當(dāng)部分節(jié)點(diǎn)不可用:

  1. 當(dāng)zone 1中的proxy 1不可用,不影響整個(gè)訪問(wèn)鏈路,其他Proxy依然可以接受請(qǐng)求。
  2. 當(dāng) zone 1 中的 QueryNode 1 不可用,會(huì)出現(xiàn)訪問(wèn)報(bào)錯(cuò)的問(wèn)題。需要重建QueryNode1,有可能在 Zone 2 新建QueryNode 5,原本請(qǐng)求QueryNode 1 的流量會(huì)重新指向 QueryNode 5。

圖片圖片

當(dāng) Zone1 不可用:

  1. 訪問(wèn)會(huì)切換到 Zone 2 的備用SLB中。
  2. 備用SLB會(huì)訪問(wèn)本機(jī)房的Proxy。
  3. 由于 QueryNode 1 和 QueryNode 2 已經(jīng)不可用,需要重建QueryNode,新生成 QueryNode 5、QueryNode 6并且加載數(shù)據(jù)提供訪問(wèn)。

圖片

方案2: 同城多zone多副本就近訪問(wèn)

正常訪問(wèn):

  1. 不同zone的客戶(hù)端訪問(wèn)本地的SLB。
  2. 使用了QueryNode多副本特性,各自zone的QueryNode都加載了所有數(shù)據(jù)。

Proxy -> QueryNode 的訪問(wèn),目前Proxy只能隨機(jī)訪問(wèn)所有zone的QueryNode(這是Milvus的限制)

圖片

當(dāng)部分節(jié)點(diǎn)不可用:

  1. 當(dāng)每個(gè)zone 都有1個(gè)Proxy故障,并不影響業(yè)務(wù)正常訪問(wèn)。
  2. 由于QueryNode開(kāi)啟了副本,只要每個(gè)zone不相同的QueryNode故障,集群還是能正常運(yùn)行。需要注意的是這時(shí)候需要考慮剩下的QueryNode性能是否滿(mǎn)足需求。所以一般業(yè)務(wù)需要有限流功能,在剩余的QueryNode不滿(mǎn)足需求時(shí),業(yè)務(wù)需要限流,直到其他QueryNode恢復(fù)。

圖片

整個(gè)Zone不可用:

  1. 當(dāng)Zone1整個(gè)不可用,不影響Zone2的訪問(wèn)。

圖片

方案3: 同城多zone單獨(dú)部署業(yè)務(wù)交叉訪問(wèn)互相backup

正常訪問(wèn):

  1. 每個(gè)zone都有單獨(dú)部署的milvus集群。
  2. 每個(gè)集群的有同時(shí)滿(mǎn)足 業(yè)務(wù)1、業(yè)務(wù)2 訪問(wèn)的數(shù)據(jù)。
  3. 業(yè)務(wù)訪問(wèn)Proxy的時(shí)候是有交叉訪問(wèn)的情況
  4. 業(yè)務(wù)改造會(huì)比較多,需要實(shí)現(xiàn)雙寫(xiě)。

圖片圖片

當(dāng)部分節(jié)點(diǎn)不可用:

  1. 當(dāng)Zone1中的Proxy1部可用,不會(huì)影響Zone1的整個(gè)集群訪問(wèn)。
  2. 當(dāng)Zone1的QueryNode1不可用,會(huì)影響到線(xiàn)路1、2的正常訪問(wèn),這時(shí)候業(yè)務(wù)需要切換不訪問(wèn)Zone1的SLB。

圖片圖片

當(dāng)整個(gè)zone不可用

  1. 整個(gè)zone1不可用,由于線(xiàn)路1會(huì)訪問(wèn)到zone1的SLB,因此線(xiàn)路1訪問(wèn)會(huì)報(bào)錯(cuò),業(yè)務(wù)需要將線(xiàn)路1切換成線(xiàn)路2。

圖片圖片

六、向量數(shù)據(jù)庫(kù)運(yùn)維沉淀

索引結(jié)構(gòu)和搜索原理

NHSW 索引

※ 相關(guān)信息

圖片

※ 內(nèi)存結(jié)構(gòu)

由于空間問(wèn)題,圖中并沒(méi)有完全按 M=16、ef=200 參數(shù)進(jìn)行畫(huà)圖。

圖片圖片

※ NHSW搜索過(guò)程

現(xiàn)在需要搜索向量N = [....]

第一步:

在第一層隨機(jī)選擇一個(gè)節(jié)點(diǎn),如:3。

圖片圖片

第二步:

  1. 。通過(guò)節(jié)點(diǎn)3,從第1層轉(zhuǎn)跳到第2層
  2. 在第2層,通過(guò)節(jié)點(diǎn)3獲取到相鄰的節(jié)點(diǎn):節(jié)點(diǎn)1、節(jié)點(diǎn)2、節(jié)點(diǎn)5、節(jié)點(diǎn)6。
  3. 將搜索節(jié)點(diǎn)N逐個(gè)和 節(jié)點(diǎn)1、節(jié)點(diǎn)2、節(jié)點(diǎn)5、節(jié)點(diǎn)6 進(jìn)行計(jì)算出各自的距離。并且選擇距離最短的節(jié)點(diǎn)6。

節(jié)點(diǎn)N -> 節(jié)點(diǎn)1:10

節(jié)點(diǎn)N -> 節(jié)點(diǎn)2:6

節(jié)點(diǎn)N -> 節(jié)點(diǎn)5:9

節(jié)點(diǎn)N -> 節(jié)點(diǎn)6:3

節(jié)點(diǎn)N -> 節(jié)點(diǎn)3:4

  1. 將 節(jié)點(diǎn)1、節(jié)點(diǎn)2、節(jié)點(diǎn)5、節(jié)點(diǎn)6、節(jié)點(diǎn)3 放入結(jié)果候選集中。

第三步:

  1. 。通過(guò)節(jié)點(diǎn)6,從第二層跳到底3層
  2. 在第3層,通過(guò)節(jié)點(diǎn)6獲取到相鄰的節(jié)點(diǎn):節(jié)點(diǎn)2、節(jié)點(diǎn)3、節(jié)點(diǎn)6、節(jié)點(diǎn)9,其中 節(jié)點(diǎn)2、節(jié)點(diǎn)3、節(jié)點(diǎn)6 已經(jīng)存在,因此只需要將 節(jié)點(diǎn)9 放入候選結(jié)果集。
  3. 如果候選結(jié)果集合沒(méi)有滿(mǎn),則繼續(xù)便利 節(jié)點(diǎn)2、節(jié)點(diǎn)3、節(jié)點(diǎn)9 的鄰居,直到 節(jié)點(diǎn)數(shù)=ef=200。

圖片

DiskANN 索引

※ 相關(guān)信息

圖片

※ 存儲(chǔ)結(jié)構(gòu)和裁剪過(guò)程

由于畫(huà)圖空間問(wèn)題,沒(méi)辦法將 聚類(lèi)數(shù)=10、100/內(nèi)存聚類(lèi)、1w/磁盤(pán)聚類(lèi) 信息畫(huà)全。

圖片圖片

  1. 初始化隨機(jī)連接:DiskANN算法會(huì)將向量數(shù)據(jù)生成一個(gè)密集的網(wǎng)絡(luò)圖,其中點(diǎn)和點(diǎn)是隨機(jī)鏈接的,并且每個(gè)點(diǎn)大概有500個(gè)鏈接。
  2. 裁剪冗余鏈接:通過(guò)計(jì)算點(diǎn)和點(diǎn)點(diǎn)距離裁剪掉一些冗余的鏈接,留下質(zhì)量高的鏈接。
  3. 添加快速導(dǎo)航鏈接:計(jì)算出圖中若干個(gè)中心點(diǎn),并且將這些中心點(diǎn)進(jìn)行鏈接,并且這些鏈接會(huì)跳過(guò)其他點(diǎn),如果圖中黃色鏈接。
  4. 重復(fù)進(jìn)行裁剪優(yōu)化過(guò)程,達(dá)到最優(yōu)的情況。
  5. PQ量化操作生成索引:

將向量分成多個(gè)子空間。

獨(dú)立對(duì)每個(gè)子空間進(jìn)行聚類(lèi)操作,并且計(jì)算出多個(gè)質(zhì)心。

將每個(gè)子向量映射到最近的質(zhì)心ID。

※ DiskANN搜索過(guò)程

現(xiàn)在需要搜索向量N = [....]

第一步(內(nèi)存索引中搜索):

將搜索的向量進(jìn)行量化。

將量化后的數(shù)據(jù)在內(nèi)存中索引尋找到離自己較近的質(zhì)心為入口進(jìn)行下一步搜索。

圖片圖片

第二步(內(nèi)存中搜索):

通過(guò)第一個(gè)節(jié)點(diǎn),尋找到它的所有相鄰節(jié)點(diǎn)。

通過(guò)內(nèi)存PQ代碼計(jì)算搜索節(jié)點(diǎn)和相鄰節(jié)點(diǎn)的近似距離。

這些鄰居節(jié)點(diǎn)都是潛在的下次搜索候選口節(jié)點(diǎn)。

圖片圖片

第三步(磁盤(pán)中搜索):

通過(guò)計(jì)算搜索節(jié)點(diǎn)和相鄰節(jié)點(diǎn)的真實(shí)距離,并且得到距離最近的一個(gè)節(jié)點(diǎn)(需要從磁盤(pán)上讀取證實(shí)的節(jié)點(diǎn)數(shù)據(jù)并計(jì)算)。

并且通過(guò)得到的最新節(jié)點(diǎn)獲取到新的相鄰節(jié)點(diǎn)。

圖片圖片

第四步(磁盤(pán)中搜索):

反復(fù)先進(jìn)二、三步驟操作,直到找到足夠數(shù)量的鄰居。

圖片圖片

并不是你想的那樣

querynode 越多越快?

querynode 越多,查詢(xún)?cè)娇?,并發(fā)越高?

※誤區(qū)原因

將querynode看成redis cluster,增加節(jié)點(diǎn)數(shù)能提高查詢(xún)并發(fā),然而并不是。redis cluster 增加節(jié)點(diǎn),數(shù)據(jù)量會(huì)盡可能的打散到每個(gè)節(jié)點(diǎn)中,所以增加節(jié)點(diǎn)和性能提升是相對(duì)成正比。但是milvus不一樣,milvus打散的基本單位是segment,一般segment大小(1G/個(gè)),他的粒度比redis cluster要大。理論上的理想情況是1個(gè)segment對(duì)應(yīng)1個(gè)querynode,但是實(shí)際情況會(huì)收到多因素的干擾,會(huì)導(dǎo)致querynode越多出現(xiàn)不穩(wěn)定的概率越大,如某個(gè)querynode網(wǎng)絡(luò)抖動(dòng)會(huì)影響整體的查詢(xún)RT。

不能提升性能例1:

部分segment數(shù) < querynode數(shù),或部分querynode沒(méi)有任何segment。

圖片圖片

不能提升性能例2:

querynode 過(guò)多,其中1個(gè)querynode RT 高,導(dǎo)致整體客戶(hù)端RT高。

圖片

標(biāo)量索引提高性能

在標(biāo)量上創(chuàng)建索引,搜索帶上標(biāo)量過(guò)來(lái)能提高性能?

※誤區(qū)原因

使用傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)的索引查詢(xún)來(lái)理解Milvus的索引查詢(xún),字段上創(chuàng)建了索引能使用到索引掃描進(jìn)行數(shù)據(jù)查詢(xún),比全表掃描快。然而并不是,關(guān)系型數(shù)據(jù)庫(kù)的屬于精確查詢(xún),Milvus屬于近似最近鄰搜索(ANNS),milvus的查詢(xún)是不保證絕對(duì)精確,使用了標(biāo)量索引查詢(xún)反而會(huì)導(dǎo)致數(shù)據(jù)變稀疏查詢(xún)會(huì)變慢。

使用標(biāo)量索引篩選不一定快原因,如下示例:

通過(guò)標(biāo)量搜索后再使用ANNS搜索過(guò)程:

1.Collection A 中的數(shù)據(jù)如下,其中is_delete 是標(biāo)量,其中的值有0和1。

圖片圖片

2.使用ANNS搜索

使用ANNS搜索能直接很快地獲取到滿(mǎn)足條件的數(shù)據(jù)。

圖片圖片

3.再使用 ANNS 搜索獲取最終數(shù)據(jù)。

圖片圖片


思考:

在第二步如果使用ANNS搜索完成之后到底是否需要使用標(biāo)量索引進(jìn)行搜索。

如果需要使用標(biāo)量索引進(jìn)行搜索那邊在ANNS搜索后的結(jié)果集需要額外的進(jìn)行索引構(gòu)建,然后再進(jìn)行過(guò)濾。構(gòu)建構(gòu)建過(guò)程其實(shí)也是需要便利結(jié)果集,那么是不是可以直接在便利的時(shí)候直接進(jìn)行結(jié)果集的篩選。

那么其實(shí)在某種程度上是不是標(biāo)量索引沒(méi)那么好用。

大量單行dml不批量寫(xiě)入能提高數(shù)據(jù)庫(kù)性能

大量單行dml,不使用批量寫(xiě)入操作,能提高數(shù)據(jù)庫(kù)性能。

※誤區(qū)原因

使用傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)為了讓系統(tǒng)盡量少的大事務(wù),減少鎖問(wèn)題并且提高數(shù)據(jù)庫(kù)性能。然而實(shí)際上Milvus如果有很多的小事務(wù)反而會(huì)影響到數(shù)據(jù)庫(kù)的性能。因?yàn)镸ilvus進(jìn)行dml操作會(huì)生成deltalog、insertlog,當(dāng)dml都是小事務(wù)就會(huì)生成大量的相對(duì)較小的deltalog和insertlog文件,deltalog和insertlog在和segment做合并的時(shí)候會(huì)增加打開(kāi)和關(guān)閉文件次數(shù),并且增加做合并次數(shù),導(dǎo)致io一直處于繁忙狀態(tài)。

deltalog 和 insertlog 生成的契機(jī)有2種:

  1. 當(dāng)數(shù)據(jù)量達(dá)到了一定的閾值會(huì)進(jìn)行生成deltalog 或 insertlog。
  2. Milvus會(huì)定時(shí)進(jìn)行生成deltalog 或 insertlog。

eltalog、insertlog  和 segment 合并過(guò)程

圖片圖片

人為讓 deltalog、segment 執(zhí)行時(shí)機(jī)可預(yù)測(cè)

如果業(yè)務(wù)對(duì)數(shù)據(jù)是實(shí)現(xiàn)要求不是那么高,建議使用定時(shí)批量的方式對(duì)數(shù)據(jù)進(jìn)行寫(xiě)入,比如可以通過(guò)監(jiān)控獲取到每天的波谷時(shí)間段,在波谷時(shí)間段內(nèi)進(jìn)行集中式數(shù)據(jù)寫(xiě)入。原因是如果不停的在做寫(xiě)入,無(wú)法判斷進(jìn)行合并segment的時(shí)間點(diǎn),要是在高峰期進(jìn)行了合并操作,很有可能會(huì)影響到集群性能。

錯(cuò)誤處理

※ 2.2.6 批量刪除數(shù)據(jù)bug,導(dǎo)致業(yè)務(wù)無(wú)法查詢(xún)

報(bào)錯(cuò):

pymilvus.exceptions.MilvusException: <MilvusException: (code=1, message=syncTimestamp Failed:err: find no available rootcoord, check rootcoord state
, /go/src/github.com/milvus-io/milvus/internal/util/trace/stack_trace.go:51 github.com/milvus-io/milvus/internal/util/trace.StackTrace
/go/src/github.com/milvus-io/milvus/internal/util/grpcclient/client.go:329 github.com/milvus-io/milvus/internal/util/grpcclient.(*ClientBase[...]).ReCall
/go/src/github.com/milvus-io/milvus/internal/distributed/rootcoord/client/client.go:421 github.com/milvus-io/milvus/internal/distributed/rootcoord/client.(*Client).AllocTimestamp
/go/src/github.com/milvus-io/milvus/internal/proxy/timestamp.go:61 github.com/milvus-io/milvus/internal/proxy.(*timestampAllocator).alloc
/go/src/github.com/milvus-io/milvus/internal/proxy/timestamp.go:83 github.com/milvus-io/milvus/internal/proxy.(*timestampAllocator).AllocOne
/go/src/github.com/milvus-io/milvus/internal/proxy/task_scheduler.go:172 github.com/milvus-io/milvus/internal/proxy.(*baseTaskQueue).Enqueue
/go/src/github.com/milvus-io/milvus/internal/proxy/impl.go:2818 github.com/milvus-io/milvus/internal/proxy.(*Proxy).Search
/go/src/github.com/milvus-io/milvus/internal/distributed/proxy/service.go:680 github.com/milvus-io/milvus/internal/distributed/proxy.(*Server).Search
/go/pkg/mod/github.com/milvus-io/milvus-proto/go-api@v0.0.0-20230324025554-5bbe6698c2b0/milvuspb/milvus.pb.go:10560 github.com/milvus-io/milvus-proto/go-api/milvuspb._MilvusService_Search_Handler.func1
/go/src/github.com/milvus-io/milvus/internal/proxy/rate_limit_interceptor.go:47 github.com/milvus-io/milvus/internal/proxy.RateLimitInterceptor.func1
)>

解決:將集群升級(jí)到2.2.16,并且讓業(yè)務(wù) 批量刪除和寫(xiě)入數(shù)據(jù)。

※ find no available rootcoord, check rootcoord state

報(bào)錯(cuò):

[2024/09/26 08:19:14.956 +00:00] [ERROR] [grpcclient/client.go:158] ["failed to get client address"] [error="find no available rootcoord, check rootcoord state"] [stack="github.com/milvus-io/milvus/internal/util/grpcclient.(*ClientBase[...]).connect
/go/src/github.com/milvus-io/milvus/internal/util/grpcclient/client.go:158
github.com/milvus-io/milvus/internal/util/grpcclient.(*ClientBase[...]).GetGrpcClient
/go/src/github.com/milvus-io/milvus/internal/util/grpcclient/client.go:131
github.com/milvus-io/milvus/internal/util/grpcclient.(*ClientBase[...]).callOnce
/go/src/github.com/milvus-io/milvus/internal/util/grpcclient/client.go:256
github.com/milvus-io/milvus/internal/util/grpcclient.(*ClientBase[...]).ReCall
/go/src/github.com/milvus-io/milvus/internal/util/grpcclient/client.go:312
github.com/milvus-io/milvus/internal/distributed/rootcoord/client.(*Client).GetComponentStates
/go/src/github.com/milvus-io/milvus/internal/distributed/rootcoord/client/client.go:129
github.com/milvus-io/milvus/internal/util/funcutil.WaitForComponentStates.func1
/go/src/github.com/milvus-io/milvus/internal/util/funcutil/func.go:65
github.com/milvus-io/milvus/internal/util/retry.Do
/go/src/github.com/milvus-io/milvus/internal/util/retry/retry.go:42
github.com/milvus-io/milvus/internal/util/funcutil.WaitForComponentStates
/go/src/github.com/milvus-io/milvus/internal/util/funcutil/func.go:89
github.com/milvus-io/milvus/internal/util/funcutil.WaitForComponentHealthy
/go/src/github.com/milvus-io/milvus/internal/util/funcutil/func.go:104
github.com/milvus-io/milvus/internal/distributed/datanode.(*Server).init
/go/src/github.com/milvus-io/milvus/internal/distributed/datanode/service.go:275
github.com/milvus-io/milvus/internal/distributed/datanode.(*Server).Run
/go/src/github.com/milvus-io/milvus/internal/distributed/datanode/service.go:172
github.com/milvus-io/milvus/cmd/components.(*DataNode).Run
/go/src/github.com/milvus-io/milvus/cmd/components/data_node.go:51
github.com/milvus-io/milvus/cmd/roles.runComponent[...].func1
/go/src/github.com/milvus-io/milvus/cmd/roles/roles.go:102"]

問(wèn)題:rootcoord和其他pod通信出現(xiàn)了問(wèn)題。

解決:先重建rootcoord,再依次重建相關(guān)的querynode、indexnode、queryrecord、indexrecord。

※ 頁(yè)面查詢(xún)報(bào)錯(cuò) 

(Search 372 failed, reason Timestamp lag too large lag)

[2024/09/26 09:14:13.063 +00:00] [WARN] [retry/retry.go:44] ["retry func failed"] ["retry time"=0] [error="Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)"]
[2024/09/26 09:14:13.063 +00:00] [WARN] [proxy/task_search.go:529] ["QueryNode search result error"] [traceID=62505beaa974c903] [msgID=452812354979102723] [nodeID=372] [reasnotallow="Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)"]
[2024/09/26 09:14:13.063 +00:00] [WARN] [proxy/task_policies.go:132] ["failed to do query with node"] [traceID=62505beaa974c903] [nodeID=372] [dmlChannels="[by-dev-rootcoord-dml_6_442659379752037218v0,by-dev-rootcoord-dml_7_442659379752037218v1]"] [error="code: UnexpectedError, error: fail to Search, QueryNode ID=372, reasnotallow=Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)"]
[2024/09/26 09:14:13.063 +00:00] [WARN] [proxy/task_policies.go:159] ["retry another query node with round robin"] [traceID=62505beaa974c903] [Nexts="{\"by-dev-rootcoord-dml_6_442659379752037218v0\":-1,\"by-dev-rootcoord-dml_7_442659379752037218v1\":-1}"]
[2024/09/26 09:14:13.063 +00:00] [WARN] [proxy/task_policies.go:60] ["no shard leaders were available"] [traceID=62505beaa974c903] [channel=by-dev-rootcoord-dml_6_442659379752037218v0] [leaders="[<NodeID: 372>]"]
[2024/09/26 09:14:13.063 +00:00] [WARN] [proxy/task_policies.go:119] ["failed to search/query with round-robin policy"] [traceID=62505beaa974c903] [error="Channel: by-dev-rootcoord-dml_7_442659379752037218v1 returns err: code: UnexpectedError, error: fail to Search, QueryNode ID=372, reasnotallow=Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)Channel: by-dev-rootcoord-dml_6_442659379752037218v0 returns err: code: UnexpectedError, error: fail to Search, QueryNode ID=372, reasnotallow=Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)"]
[2024/09/26 09:14:13.063 +00:00] [WARN] [proxy/task_search.go:412] ["failed to do search"] [traceID=62505beaa974c903] [Shards="map[by-dev-rootcoord-dml_6_442659379752037218v0:[<NodeID: 372>] by-dev-rootcoord-dml_7_442659379752037218v1:[<NodeID: 372>]]"] [error="code: UnexpectedError, error: fail to Search, QueryNode ID=372, reasnotallow=Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)"]
[2024/09/26 09:14:13.063 +00:00] [WARN] [proxy/task_search.go:425] ["first search failed, updating shardleader caches and retry search"] [traceID=62505beaa974c903] [error="code: UnexpectedError, error: fail to Search, QueryNode ID=372, reasnotallow=Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)"]
[2024/09/26 09:14:13.063 +00:00] [INFO] [proxy/meta_cache.go:767] ["clearing shard cache for collection"] [collectinotallow=xxx]
[2024/09/26 09:14:13.063 +00:00] [WARN] [retry/retry.go:44] ["retry func failed"] ["retry time"=0] [error="code: UnexpectedError, error: fail to Search, QueryNode ID=372, reasnotallow=Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)"]
[2024/09/26 09:14:13.063 +00:00] [WARN] [proxy/task_scheduler.go:473] ["Failed to execute task: "] [error="fail to search on all shard leaders, err=All attempts results:\nattempt #1:code: UnexpectedError, error: fail to Search, QueryNode ID=372, reasnotallow=Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)\nattempt #2:context canceled\n"] [traceID=62505beaa974c903]
[2024/09/26 09:14:13.063 +00:00] [WARN] [proxy/impl.go:2861] ["Search failed to WaitToFinish"] [traceID=62505beaa974c903] [error="fail to search on all shard leaders, err=All attempts results:\nattempt #1:code: UnexpectedError, error: fail to Search, QueryNode ID=372, reasnotallow=Search 372 failed, reason Timestamp lag too large lag(28h44m48.341s) max(24h0m0s) err %!w(<nil>)\nattempt #2:context canceled\n"] [role=proxy] [msgID=452812354979102723] [db=] [collectinotallow=xxx] [partitinotallow="[]"] [dsl=] [len(PlaceholderGroup)=4108] [OutputFields="[id,text,extra]"] [search_params="[{\"key\":\"params\",\"value\":\"{\\\"ef\\\":250}\"},{\"key\":\"anns_field\",\"value\":\"vector\"},{\"key\":\"topk\",\"value\":\"100\"},{\"key\":\"metric_type\",\"value\":\"L2\"},{\"key\":\"round_decimal\",\"value\":\"-1\"}]"] [travel_timestamp=0] [guarantee_timestamp=0]

問(wèn)題:pulsar 組件對(duì)應(yīng)相關(guān)pod問(wèn)題導(dǎo)致不進(jìn)行消費(fèi)。

解決:將pulsar 組件相關(guān)pod進(jìn)行重建,查看日志,并且等待消費(fèi)pulsar完成。

※ Query Node 限制內(nèi)存不足

 (memory quota exhausted)

報(bào)錯(cuò):

<MilvusException: (code=53, message=deny to write, reason: memory quota exhausted, please allocate more resources, req: /milvus.proto.milvus.MilvusService/Insert)>

原因:配置中Query Node配置內(nèi)存上線(xiàn)達(dá)到瓶頸。

解決:增加Query Node配置或者增加QueryNode節(jié)點(diǎn)數(shù)。

※ 底層磁盤(pán)瓶頸導(dǎo)致ETCD訪問(wèn)超時(shí)

報(bào)錯(cuò):

圖片圖片

解決:從架構(gòu)方面上進(jìn)行解決,在集群維度將磁盤(pán)進(jìn)行隔離,每個(gè)集群使用獨(dú)立磁盤(pán)。

七、未來(lái)展望

數(shù)據(jù)遷移閉環(huán)

數(shù)據(jù)遷移閉環(huán):對(duì)于業(yè)務(wù)數(shù)據(jù)加載到向量數(shù)據(jù)庫(kù)的場(chǎng)景,業(yè)務(wù)只關(guān)心數(shù)據(jù)的讀取和使用,不需要關(guān)心數(shù)據(jù)的量化和寫(xiě)入。DBA側(cè)建立數(shù)據(jù)遷移閉環(huán)(下圖綠色部分)。

數(shù)據(jù)準(zhǔn)確性校驗(yàn)

對(duì)于上游數(shù)據(jù)(如MySQL)和下游向量數(shù)據(jù)庫(kù)數(shù)據(jù)庫(kù)一致性校驗(yàn)問(wèn)題,DBA業(yè)將協(xié)同業(yè)務(wù)、Milvus進(jìn)行共建校驗(yàn)工具,保障數(shù)據(jù)的準(zhǔn)確性。

圖片圖片

責(zé)任編輯:武曉燕 來(lái)源: 得物技術(shù)
相關(guān)推薦

2023-03-30 18:39:36

2022-12-14 18:40:04

得物染色環(huán)境

2022-12-09 18:58:10

2023-12-27 18:46:05

云原生容器技術(shù)

2024-03-07 10:09:42

向量數(shù)據(jù)庫(kù)

2023-11-17 07:30:30

線(xiàn)段pgvector實(shí)踐

2025-11-11 01:55:00

2023-10-09 18:35:37

得物Redis架構(gòu)

2025-03-13 06:48:22

2023-11-27 18:38:57

得物商家測(cè)試

2023-02-08 18:33:49

SRE探索業(yè)務(wù)

2023-11-27 00:58:00

數(shù)據(jù)庫(kù)AI

2023-07-19 22:17:21

Android資源優(yōu)化

2023-08-09 20:43:32

2022-10-26 18:44:33

藍(lán)紙箱設(shè)計(jì)數(shù)據(jù)

2022-09-01 07:23:53

云原生數(shù)據(jù)庫(kù)Aurora

2025-03-20 10:47:15

2022-10-20 14:35:48

用戶(hù)畫(huà)像離線(xiàn)

2023-03-13 18:35:33

灰度環(huán)境golang編排等
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

97人妻人人揉人人躁人人| 国产一区二区三区在线免费| 波多野结衣av无码| 91日韩欧美| 日韩免费在线观看| 日本国产在线播放| 国产精品一级伦理| 麻豆一区二区三区| 欧美日韩国产123| 中文字幕丰满孑伦无码专区| a屁视频一区二区三区四区| 日韩毛片视频在线看| 极品日韩久久| 一级黄色片在线看| 夜夜夜久久久| 最近更新的2019中文字幕| 色欲欲www成人网站| 少妇在线看www| 国产精品美女久久久久久2018| 亚洲在线一区二区| 综合网在线观看| 欧美不卡在线| 国产亚洲一区二区精品| 无码人妻少妇色欲av一区二区| 黄网页在线观看| 日本亚洲三级在线| 久久久久久久一| 性爱在线免费视频| 婷婷成人影院| 日韩欧美国产午夜精品| 国产免费999| av资源在线| 亚洲欧美一区二区不卡| 欧美成人综合一区| 好吊视频一二三区| 韩国欧美一区二区| 国产精品精品久久久| 日韩 欧美 精品| 888久久久| 在线视频中文亚洲| 国产精品揄拍100视频| 亚洲专区**| 91麻豆精品国产91久久久使用方法 | 国产成人久久精品一区二区三区| 欧美日韩免费区域视频在线观看| 日本一二三区视频在线| 91美女视频在线| 国产日韩影视精品| 久久久com| 欧美熟妇乱码在线一区| 国产精品中文字幕欧美| 成人黄色片在线| 艳妇乳肉豪妇荡乳av无码福利| 亚洲一区二区三区高清| 国模精品一区二区三区色天香| 日韩欧美123区| 香蕉精品视频在线观看| 在线观看久久久久久| 天天躁日日躁aaaa视频| 欧美精品momsxxx| 亚洲精选中文字幕| 欧美色图亚洲激情| 精品国产aⅴ| 一区二区在线免费视频| 日韩一级av毛片| 精品国产网站| 日韩在线观看网站| 最新av电影网站| 亚洲精品成人影院| 欧美床上激情在线观看| 久草资源在线视频| 亚洲国产三级| 91国内在线视频| 日本中文字幕第一页| 久久一区激情| 国产免费亚洲高清| 99re只有精品| 成人国产亚洲欧美成人综合网| 国模精品娜娜一二三区| 五月婷婷在线播放| 国产亚洲欧美在线| 亚洲精品国产精品国自产| 午夜伦理在线| 一区二区三区丝袜| av动漫在线看| 成人综合网站| 欧美大肚乱孕交hd孕妇| 美女又爽又黄免费| blacked蜜桃精品一区| 久久精品亚洲国产| 精品少妇一二三区| 噜噜噜久久亚洲精品国产品小说| 国产欧美日韩精品在线观看| 国产乱叫456在线| 成+人+亚洲+综合天堂| 欧美 日韩 国产在线| 香港伦理在线| 亚洲国产成人tv| 久久久国产欧美| 国产亚洲字幕| 日韩精品视频在线观看免费| 91麻豆制片厂| 国内在线观看一区二区三区| 国产91精品久久久| 一本色道久久综合亚洲| 成人精品视频一区二区三区| 欧洲精品久久| 亚洲丝袜精品| 色噜噜偷拍精品综合在线| 一级 黄 色 片一| 亚洲高清极品| 理论片在线不卡免费观看| 狠狠躁夜夜躁人人爽天天高潮| 日本少妇一区二区| 99久久自偷自偷国产精品不卡| 人成免费电影一二三区在线观看| 亚洲女同女同女同女同女同69| 99久热在线精品视频| 少妇一区视频| 日韩欧美成人午夜| 国产精品久久免费观看| 黄色另类av| 成人在线视频网站| 理论视频在线| 岛国av一区二区三区| 911av视频| 欧美限制电影| 欧美在线播放视频| 亚洲女人18毛片水真多| 国产精品久久夜| 欧美xxxxx在线视频| 97久久综合精品久久久综合| 久久好看免费视频| 中文字幕有码视频| 久久久久九九视频| 蜜桃传媒一区二区三区| 日韩成人视屏| 最新的欧美黄色| av毛片在线免费观看| 成人蜜臀av电影| 日韩成人午夜影院| 青青在线精品| 亚洲最新中文字幕| 久草视频一区二区| 91在线国内视频| 99在线精品免费视频| 中文字幕一区图| 欧美成人免费视频| www.中文字幕| 亚洲美女偷拍久久| 国产精品久久久久久久99| 精品久久精品| 国产成人久久久| 牛牛影视精品影视| 色综合久久久久综合体| a级大片在线观看| 亚洲破处大片| 亚洲sss综合天堂久久| 男人av在线| 在线亚洲人成电影网站色www| 日韩人妻一区二区三区| 亚洲永久字幕| 奇米精品在线| 久久91视频| 最近2019中文字幕第三页视频 | 日本韩国欧美三级| a级大片在线观看| 日韩电影一二三区| 午夜久久资源| 成人免费观看49www在线观看| 久久黄色av网站| 亚洲精品97久久中文字幕| 亚洲午夜精品17c| 岛国精品资源网站| 西西裸体人体做爰大胆久久久| 久久精品日韩| 色综合天天色| 不卡伊人av在线播放| 亚洲精品国产精品国| 天天av天天翘天天综合网| 日本一区二区三区网站| 日韩av网站免费在线| 99re99热| 精品亚洲免a| 国产精品wwwwww| 国产91在线视频蝌蚪| 亚洲第一中文字幕| 日韩一级在线视频| 亚洲素人一区二区| 亚洲啪av永久无码精品放毛片| 午夜在线观看免费一区| 一本久道久久综合| 成人动态视频| 国产精品电影网站| 国产日产一区二区三区| 亚洲爱爱爱爱爱| 一级黄色在线观看| 一区二区三区欧美| 极品粉嫩小仙女高潮喷水久久| 日韩精品色哟哟| 青青草综合在线| 精品国产99| 国产高清自拍一区| h1515四虎成人| 国产+成+人+亚洲欧洲| 99视频在线观看地址| 精品久久国产老人久久综合| 欧美视频xxxx| 亚洲国产精品久久久久秋霞影院| 一二三四在线观看视频| 成年人国产精品| 手机在线国产视频| 亚洲自拍另类| 国产小视频免费| 日韩精品2区| 精品欧美一区二区在线观看视频| 四虎影视国产精品| 日韩av成人在线观看| 伊人精品影院| 色哟哟入口国产精品| 色呦呦视频在线| 欧美一区二区三级| 国产精品传媒在线观看| 亚洲成a人v欧美综合天堂下载| 国产乱子轮xxx农村| 久久综合一区二区| 香蕉久久久久久av成人| 久久爱另类一区二区小说| 国产在线青青草| 欧美视频网站| 日韩第一页在线观看| 国产欧美一区二区三区精品观看| av一区二区三区免费| 亚洲综合资源| 国产欧美精品一区二区| 欧美电影免费观看| 97久久伊人激情网| 制服丝袜中文字幕在线| 中文字幕在线成人| 精品无人乱码| 亚洲欧美中文字幕在线一区| 三级理论午夜在线观看| 精品少妇一区二区三区视频免付费 | 美女在线视频一区二区| 久久福利一区| 国产精品宾馆在线精品酒店| 亚洲午夜一级| 国产黄色激情视频| 欧美激情综合| 欧美少妇一区二区三区| 亚洲蜜桃视频| 国产卡一卡二在线| 久久久久av| 蜜臀av.com| 午夜精品视频| 国产欧美精品aaaaaa片| 欧美全黄视频| 亚洲理论电影在线观看| 一区三区视频| 欧美成人三级在线视频| 国产亚洲午夜| 亚洲爆乳无码专区| 日韩电影免费在线看| 黄色成人免费看| 老色鬼精品视频在线观看播放| 亚洲美女爱爱视频| 国产精品一区免费在线观看| 亚洲一区二区三区三州| 国产91丝袜在线18| 久久久老熟女一区二区三区91| 成人avav影音| 99久久久无码国产精品性| 国产三级欧美三级| 国产精品视频在| 中文字幕色av一区二区三区| 亚洲不卡在线播放| 亚洲国产欧美日韩另类综合 | 51午夜精品| 哺乳一区二区三区中文视频| 精品国产一区二区三区免费| 免费成人av| 一区中文字幕在线观看| 欧美午夜视频| 国产精品沙发午睡系列| 日本视频一区二区三区| 激情久久综合网| 不卡的看片网站| 老头老太做爰xxx视频| 亚洲欧美在线另类| 日本亚洲色大成网站www久久| 日韩欧美国产黄色| 91丨porny丨在线中文| 精品国产电影一区二区| 精品乱码一区二区三四区视频| 中文字幕一精品亚洲无线一区| 在线中文免费视频| 日本高清不卡的在线| 91精品国产色综合久久不卡粉嫩| 国产精品视频免费一区| 欧美日韩在线播放视频| www成人免费| 视频一区欧美日韩| 国产精品二区视频| 国产亚洲精久久久久久| 伊人在线视频观看| 色综合久久99| 精品黑人一区二区三区在线观看| 精品亚洲精品福利线在观看| 含羞草www国产在线视频| 欧美一二三视频| 国产999精品在线观看| 蜜桃视频成人| 欧美日本三区| 手机在线免费观看毛片| 成人国产免费视频| 性欧美疯狂猛交69hd| 色偷偷一区二区三区| www精品国产| 中文字幕亚洲激情| 亚洲黄色网址| 国产精品手机在线| 亚洲国产成人精品女人| 五月婷婷狠狠操| 91女神在线视频| 精品肉丝脚一区二区三区| 制服丝袜av成人在线看| 国产在线日本| 欧美在线影院在线视频| 日韩一区二区三区精品| 亚洲人成网站在线观看播放| 国产视频一区免费看| 又黄又色的网站| 综合电影一区二区三区 | 日本在线观看高清完整版| 国产在线不卡精品| 欧美限制电影| 亚洲视频在线观看一区二区三区| 91美女片黄在线观看91美女| 国产亚洲精品久久777777| 日韩欧美在线1卡| 黄色网在线免费观看| 国产日韩欧美日韩| gogogo高清在线观看一区二区| 国产精品少妇在线视频| 91丨九色丨黑人外教| 成年免费在线观看| 亚洲激情视频网站| а√在线中文在线新版 | 亚洲精品进入| 各处沟厕大尺度偷拍女厕嘘嘘| 成人av电影在线观看| 久久久久久久九九九九| 欧美变态凌虐bdsm| 七七成人影院| 国产麻豆乱码精品一区二区三区| 亚洲一级网站| 久久久久麻豆v国产精华液好用吗| 亚洲永久免费av| 亚洲奶汁xxxx哺乳期| 国内精品小视频在线观看| 日韩在线影视| 91淫黄看大片| 国产精品网站在线播放| 亚洲在线视频播放| 久久精品免费电影| 99精品中文字幕在线不卡| www.av蜜桃| 久久在线免费观看| 最近日韩免费视频| 久久久精品国产亚洲| 久久久久久久久成人| 国产91沈先生在线播放| av一二三不卡影片| 国产精品男女视频| 亚洲天堂男人天堂女人天堂| 成人午夜毛片| 国产欧美123| 肉色超薄丝袜脚交| 亚洲国产精品一区二区www| 日韩一区二区三区中文字幕| 国产精品成人aaaaa网站| 久久久久蜜桃| 插我舔内射18免费视频| 91福利视频网站| 麻豆传媒视频在线观看免费| 成人永久免费| 久久亚洲风情| 成人免费精品动漫网站| 亚洲加勒比久久88色综合| 欧美日韩五区| 欧美高清中文字幕| 久久久蜜桃精品| 国产av一区二区三区精品| 孩xxxx性bbbb欧美| 成人久久一区| 日本天堂在线播放| 欧美亚洲国产一区在线观看网站| av毛片在线| 日韩精品另类天天更新| 国产剧情一区在线|