向量儲存和檢索解決方案--Vearch
1、摘要
vearch是對大規模深度學習向量進行高效能相似搜尋的向量檢索資料庫,可以輕鬆應對海量的向量資料的儲存和檢索。(原始碼地址:https://github.com/vearch/vearch,文件地址:https://vearch.readthedocs.io/zh_CN/latest/。)
vearch部署架構簡單,提供RESTful Api 操作,使用起來非常方便。使用vearch作為向量檢索服務,演算法工程師可以更加專注於研究演算法效果的提升。
下面通過vearch 系統架構,功能特性,系統部署,系統應用,這幾個方面進行介紹,從中會穿插介紹vearch的一些高階特性,旨在使用者能夠輕鬆構建自己的vearch服務,對vearch有一個全面的認識和了解。
2、系統架構
vearch 分為3個模組,其中包括 master、router和PartitionServer(簡稱ps)。
Master: 負責元資料管理和叢集資源協調。
Router: 提供RESTful API: create、delete、search、update; 請求路由轉發及結果合併。
PartitionServer(PS): 基於raft複製的文件分片; Gamma向量搜尋引擎,它提供了儲存、索引和檢索向量、標量的能力。
3、功能特性
RESTful API ;
資料持久化儲存,高可靠性;
高可用;
高效能;
高召回率;
4、系統部署
vearch 部署便捷,我們常用的方式,可以採用容器化的方式進行快速部署,這裡提供兩種部署架構,採用docker容器化和k8s的方式都可以實現。
4.1、部署架構
a、快速分散式部署
b、etcd+vearch分散式部署
如果你對etcd比較熟悉,或者有現成的etcd服務,那可以使用b的部署架構(後續會提供完整文件),ps和router可通過域名的方式進行部署。
為了操作簡單,下面我們介紹一下基於docker容器化,a的快速分散式部署方案:
採用一臺物理機,建立多個docker容器。現在我們需要部署節點為:master 1個、router 1個、ps 3個,總共5個節點,即建立5個docker容器。如果你採用的是多臺物理機搭建docker環境,需要注意容器之間的連通性,ip地址和埠的配置。
4.2、docker容器化部署
4.2.1、啟動vearch容器
首先我們需要下載vearch 的docker 映象。
執行:
|
執行docker images 檢視映象是否存在:找到vearch v3.2.0
修改配置檔案:(可以使用docker固定IP的方式,需要提前知道 master的ip地址,假設我們這裡保證master的ip 為172.17.0.2),修改後的配置檔案如下。
|
執行下面的命令,建立docker容器。說明:master1:7810埠是master restful 埠號,包括建立表和查詢的一些功能介面,2370是etcd埠號,可以使用etcdctl工具查詢元資料資訊。
|
如下圖:
5個節點都啟動成功。
4.2.2、環境驗證
a、執行:curl localhost:7810(保證docker埠對映成功),或者 啟動另外一個centos docker環境。
啟動 另外一個centos 容器:docker run -it centos:centos7 ,執行:curl 172.17.0.2:7810,返回叢集狀態資訊,說明vearch master啟動成功。
b、叢集整體驗證:如下,master的ip地址和埠號為172.17.0.2:7810。
執行:curl172.17.0.2:7810/list/server
獲取叢集全部的ps節點資訊。
得到json結果,如下:
執行完以上步驟,那麼vearch叢集就已經搭建完成了。
4.3、k8s 環境部署
後續會提供完整文件,可先根據前面的docker環境部署進行探索。
5、功能驗證
從系統應用的角度,把基本功能驗證流程走一遍(詳細的功能API文件參考:https://vearch.readthedocs.io/zh_CN/latest/)。功能驗證的同時,穿插加入高可用和擴容、縮容的介紹。
資料來源於真實業務場景歷史資料,使用者在測試使用時,需要根據業務需求進行合理的選擇。
這裡指定兩個變數:
a、master_server指的是master服務的ip地址和埠號[masterIP:7810]。為了方便操作,可以將docker容器的埠對映到物理機,此時masterIP指的就是物理宿主機ip。
b、router_server指的是router服務的IP地址和埠號[routerIP:8230]。,此時routerIP指的也是物理宿主機ip。
5.1、建表
a、建庫
|
b、建表 :16 維向量,檢索型別:IVFPQ 1個分割槽,3個副本。
|
驗證一下是否建立成功:
|
5.2、資料插入
5.2.1、指定docId[可根據id查詢doc] ,(檢視,確認一下router1 的ip地址 docker inspect <router 1 的docker id>,此處為 172.17.0.3)
|
5.2.2、不指定docId
|
返回結果:
{"_index":"ts_db_1","_type":"ts_space_1","_id":"5e7de70eE1d0e2912268d0db90558041d.jpg","status":200}
可根據status判斷資料是否插入成功。status = 200代表成功。
5.2.3、資料正確性
資料插入成功,可通過以下方式檢驗資料正確性:
a、根據插入成功資料量,插入成功的資料量和系統的資料量一致。插入成功的資料量,使用者可自己統計記錄,系統資料量查詢方式:可查詢partition每個副本包含的資料量。
|
資料格式如下:
Tips:資料插入過程,會出現丟資料的情況嗎?
vearch採用raft 來保證資料的一致性和正確性。raft commit 資料時,已經將資料寫入到了多數的節點上,才會返回成功,即使leader出現故障,也會重新選舉出擁有最新資料的節點作為leader繼續進行資料的寫入。不會出現丟失資料的情況。
b、插入資料按照指定docId進行(在下一節資料查詢中介紹方法),隨機抽取資料的docId,查詢系統是否正確返回資料。
c、觀察3個副本,每個副本的資料量是否保持一致。
5.3、資料查詢
a、根據id查詢:
|
b、向量檢索:
|
5.4、高可用
vearch採用多副本的模式,每個partition都可以建立多個副本,只要系統中的副本存活數大於1/2,既可以保證系統的可用性。
例子:我們上面建立的庫表 [ts_db_1/ts_space_1] ,1個partition建立3個副本;partitionID 1,replicasIDs[1,2,3]。leader 的數值是1,代表server 為1的節點,現在是partitionID為1的raft組的leader。
可以通過:curl172.17.0.2:7810/list/server 檢視。也可通過 etcdctl 檢視元資料。
高可用場景的驗證方法:
a、partition 的某個非leader副本故障:leader正常,資料的寫入是正常的;如果該副本,經過一段時間後,重啟成功,該副本會自動同步leader節點的資料至恢復到最新資料。如果副本故障,無法重啟恢復,可通過擴容增加一個副本(參見擴容、縮容)。
故障的副本,可以通過 :curl 172.17.0.2:7810/_cluster/health 驗證,資料量是否恢復一致。(參見:資料正確性)
b、leader副本故障:leader節點故障,會出現短暫的資料無法寫入,秒級時間會重新選出新的leader,資料寫入會恢復正常,故障的副本也可重啟恢復或擴容恢復。
副本故障,不斷的寫入資料,觀察資料的返回狀態,1、統計插入成功的資料量與系統資料量是否一致;(正確性驗證)2、觀察非leader副本故障,資料的寫入和讀取是否正常(正常);3、觀察leader副本故障,資料的寫入讀取是否正常(秒級 leader切換,資料短暫不可寫,很快會恢復)。
5.5、擴容、縮容
回顧一下,我們現在是總共5個節點 3個ps節點,假如系統流量高峰,需要擴容,或者高峰過後需要縮容,可以通過下面的方法進行ps節點擴容。(router節點擴容,直接增加新的節點即可)
5.5.1、擴容
擴容,首先我們需要增加新的節點加入叢集。
a、nohup
docker run --name ps4 -
v
$PWD
/config
.toml:
/vearch/config
.toml vearch
/vearch
:3.2.0
ps
> ps4.log 2>&1 &
執行:curl 172.17.0.2:7810/list/server,檢視新增節點的nodeId,partitions資訊為空。
可以看到,新增的節點,node_id為4。
執行建立副本命令,說明:method = 0代表新增副本,method = 1代表減少副本。node_id為需要操作的節點id。
|
再次通過curl 172.17.0.2:7810/list/server查詢。
5.5.2、縮容
縮容操作命令為:
|
其他的查詢命令同擴容一致。
6、總結
vearch提供了完善的分散式環境下的向量儲存和檢索服務。內容從容器化部署,到實際應用場景都進行了詳細的介紹。同時還介紹了資料正確性的驗證方法,高可用的驗證方法,副本的擴容和縮容方法以及高召回率。服務恢復釋出,版本升級,也不會影響服務的查詢效能。
下表為一些相關特性總結:
硬體環境 | 資料正確性 | 高可用 | 擴容、縮容 | 高召回率 | 備註 |
---|---|---|---|---|---|
docker 環境: 1 router 硬體指標:4c,8G 3 ps 硬體指標:16c,32G | 與插入成功的資料量一致,不存在資料丟失。 | 支援多副本,副本故障數小於副本總數的1/2,保證系統的百分之百可用性。 | 很好的支援副本的擴容和縮容。 | 支援多種索引,有高召回率。 |
召回測試
測試方法
方法說明:用vearch的hnsw召回模型與暴力搜尋在公開人臉資料集上做召回對比。
資料集:VGGFace2的300萬人臉資料集
特徵模型:Inception-resnet , 提取的特徵向量維度為512
測試資料:從300萬人臉特徵向量中隨機抽取1萬特徵向量做為搜尋測試資料
建庫資料:除去1萬測試資料,剩下的299萬人臉特徵向量全部插入vearch進行建庫
測試結果
召回模型 | 識別總次數 | 識別成功次數 | 識別準確率 | 相對暴力搜尋召回率 |
暴力搜尋 | 10000 | 9658 | 96.58% | 100% |
HNSW | 10000 | 9630 | 96.30% | 99.71%=9630/9658 |
結論:300萬數量級時,HNSW相比暴力搜尋的召回率為99.71%
效能測試
測試說明:效能測試仍然是向vearch中插入299萬基於VGGFace2人臉資料集的特徵向量,然後測試search的效能
測試部署:vearch所有服務都部署在 docker(k8s)平臺上
master:1臺4c8g
router:3臺 8c8g (避免router成為效能瓶頸,所以多部署了兩臺)
ps:1臺 8c16G (叢集資源核心)
測試結果
召回模型 | 併發 | QPS | 平均latency | tp99 | cpu | memory |
暴力搜尋 | 1 | 2.5 | 385ms | 540ms | 800% | 7.6G |
HNSW | 1 | 57 | 15ms | 20ms | 23% | 7.95G |
暴力搜尋 | 30 | none | none | none | none | none |
HNSW | 30 | 1309 | 19ms | 75ms | 800% | 8G |
備註:表中的“none”表示沒有測試的意義,放棄測試
結論:在相同的硬體資源情況下,HNSW的搜尋效能是暴力搜尋的>100倍