管理資源群組
在 Milvus 中,您可以透過資源群組將某些查詢節點與其他節點進行物理隔離。本指南將引導您了解如何建立和管理自訂資源群組,以及如何在不同資源群組之間移轉節點。
何謂資源群組
一個資源群組可以包含 Milvus 叢集中的部分或所有查詢節點。 您可以根據自身需求,決定如何將查詢節點分配至各資源群組。例如,在多集合的場景中,您可以將適當數量的查詢節點分配給每個資源群組,並將集合載入至不同的資源群組,使每個集合內的操作在物理上獨立於其他集合的操作。
請注意,Milvus 實例在啟動時會維護一個預設資源群組來容納所有查詢節點,並將其命名為__default_resource_group。
自 2.4.1 版本起,Milvus 提供宣告式資源群組 API,而舊版資源群組 API 已宣告為過時。新的宣告式 API 讓使用者能夠實現冪等性,並更輕鬆地在雲原生環境中進行次要開發。
資源群組的概念
資源群組由資源群組配置來定義:
{
"requests": { "nodeNum": 1 },
"limits": { "nodeNum": 1 },
"transfer_from": [{ "resource_group": "rg1" }],
"transfer_to": [{ "resource_group": "rg2" }]
}
- requests屬性指定資源群組必須滿足的條件。
- limits屬性指定資源群組的最大限制。
- transfer_from和transfer_to屬性分別描述該資源群組應優先從哪些資源群組獲取資源,以及應將資源轉移至哪些資源群組。
一旦資源群組的配置發生變更,Milvus 將根據新配置盡可能調整當前的查詢節點資源,以確保所有資源群組最終皆符合以下條件:
.requests.nodeNum < nodeNumOfResourceGroup < .limits.nodeNum.
但以下情況除外:
- 當 Milvus 叢集中的 QueryNodes 數量不足時,即
NumOfQueryNode < sum(.requests.nodeNum),總會存在某些資源群組的 QueryNodes 數量不足。 - 當 Milvus 叢集中的查詢節點數量過多時,即
NumOfQueryNode > sum(.limits.nodeNum),多餘的查詢節點將始終優先分配至__default_resource_group。
當然,若叢集中的 QueryNodes 數量發生變化,Milvus 會持續嘗試進行調整以符合最終條件。因此,您可以先套用資源群組的配置變更,然後再執行 QueryNode 的擴展。
使用宣告式 API 管理資源群組
本頁所有程式碼範例均基於 PyMilvus 3.0.1。執行前請先升級您的 PyMilvus 安裝版本。
建立資源群組。
要建立資源群組,請在連線至 Milvus 實例後執行以下指令。以下程式碼片段假設
default是您的 Milvus 連線別名。import pymilvus # A resource group name should be a string of 1 to 255 characters, starting with a letter or an underscore (_) and containing only numbers, letters, and underscores (_). name = "rg" node_num = 0 # create a resource group that exactly hold no query node. try: milvus_client.create_resource_group(name, config=ResourceGroupConfig( requests={"node_num": node_num}, limits={"node_num": node_num}, )) print(f"Succeeded in creating resource group {name}.") except Exception: print("Failed to create the resource group.")列出資源群組。
建立資源群組後,您即可在資源群組清單中看到該群組。
若要檢視 Milvus 實例中的資源群組清單,請依下列步驟操作:
rgs = milvus_client.list_resource_groups() print(f"Resource group list: {rgs}") # Resource group list: ['__default_resource_group', 'rg']描述資源群組。
您可以透過以下方式讓 Milvus 描述特定資源群組:
info = milvus_client.describe_resource_group(name) print(f"Resource group description: {info}") # Resource group description: # ResourceGroupInfo: # <name:rg1>, // resource group name # <capacity:0>, // resource group capacity # <num_available_node:1>, // resource group node num # <num_loaded_replica:{}>, // collection loaded replica num in resource group # <num_outgoing_node:{}>, // node num which still in use by replica in other resource group # <num_incoming_node:{}>, // node num which is in use by replica but belong to other resource group # <config:{}>, // resource group config # <nodes:[]> // node detail info在資源群組之間移動節點。
您可能會注意到,該資源群組目前尚未包含任何查詢節點。請依照以下步驟,將部分節點從預設資源群組移至您所建立的資源群組: 假設叢集的__default_resource_group中目前有 1 個 QueryNode,且我們希望將其中一個節點移至已建立的資源群組中。
update_resource_groups可確保多項配置變更的原子性,因此 Milvus 不會看到任何中間狀態。source = '__default_resource_group' target = 'rg' expected_num_nodes_in_default = 0 expected_num_nodes_in_rg = 1 try: milvus_client.update_resource_groups({ source: ResourceGroupConfig( requests={"node_num": expected_num_nodes_in_default}, limits={"node_num": expected_num_nodes_in_default}, ), target: ResourceGroupConfig( requests={"node_num": expected_num_nodes_in_rg}, limits={"node_num": expected_num_nodes_in_rg}, ) }) print(f"Succeeded in move 1 node(s) from {source} to {target}.") except Exception: print("Something went wrong while moving nodes.") # After a while, succeeded in moving 1 node(s) from __default_resource_group to rg.將集合與分區載入至資源群組。
一旦資源群組中存在查詢節點,即可將集合載入至該資源群組。以下程式碼片段假設已存在一個名為
demo的集合。from pymilvus import Collection collection_name = "demo" # Milvus loads the collection to the default resource group. milvus_client.load_collection(collection_name, replica_number=2) # Or, you can ask Milvus load the collection to the desired resource group. # make sure that query nodes num should be greater or equal to replica_number resource_groups = ['rg'] milvus_client.load_collection(replica_number=2, _resource_groups=resource_groups)此外,您也可以僅將一個分區載入至資源群組,並讓其副本分散於多個資源群組中。以下範例假設已存在名為
Books的集合,且該集合包含一個名為Novels的分區。collection = "Books" partition = "Novels" # Use the load method of a collection to load one of its partition milvus_client.load_partitions(collection, [partition], replica_number=2, _resource_groups=resource_groups)請注意,
_resource_groups為可選參數;若未指定此參數,Milvus 會將副本載入至預設資源群組中的查詢節點上。若要讓 Milvus 將集合的每個副本載入至不同的資源群組中,請確保資源群組的數量等於副本的數量。
在資源群組之間傳輸副本。
Milvus 透過副本在分佈於多個查詢節點的區段之間實現負載平衡。您可以依照以下步驟,將集合的特定副本從一個資源群組移至另一個資源群組:
source = '__default_resource_group' target = 'rg' collection_name = 'c' num_replicas = 1 try: milvus_client.transfer_replica(source, target, collection_name, num_replicas) print(f"Succeeded in moving {num_replicas} replica(s) of {collection_name} from {source} to {target}.") except Exception: print("Something went wrong while moving replicas.") # Succeeded in moving 1 replica(s) of c from __default_resource_group to rg.刪除資源群組。
您可以隨時刪除未包含任何查詢節點的資源群組(
limits.node_num = 0)。在本指南中,資源群組rg目前包含一個查詢節點。您需要先將該資源群組的配置limits.node_num修改為零。resource_group = "rg try: milvus_client.update_resource_groups({ resource_group: ResourceGroupConfig( requests={"node_num": 0}, limits={"node_num": 0}, ), }) milvus_client.drop_resource_group(resource_group) print(f"Succeeded in dropping {resource_group}.") except Exception: print(f"Something went wrong while dropping {resource_group}.")
更多詳細資訊,請參閱pymilvus 中的相關範例
管理叢集擴展的良好實務
目前,Milvus 無法在雲原生環境中獨立進行擴展與縮減。然而,透過結合使用宣告式資源群組 API與容器調度,Milvus 能夠輕鬆實現 QueryNodes 的資源隔離與管理。 以下是在雲端環境中管理 QueryNodes 的最佳實務:
預設情況下,Milvus 會建立一個__default_resource_group。此資源群組無法刪除,同時也作為所有集合的預設載入資源群組,且冗餘的 QueryNodes 總是會被指派至該群組。 因此,我們可以建立一個「待處理」資源群組來存放閒置的 QueryNode 資源,防止這些資源被__default_resource_group 佔用。
此外,若嚴格執行
sum(.requests.nodeNum) <= queryNodeNum此限制條件,即可精確控制叢集內 QueryNodes 的分配。假設叢集中目前僅有一台 QueryNode,並初始化該叢集。 以下為設定範例:from pymilvus.client.types import ResourceGroupConfig _PENDING_NODES_RESOURCE_GROUP="__pending_nodes" def init_cluster(node_num: int): print(f"Init cluster with {node_num} nodes, all nodes will be put in default resource group") # create a pending resource group, which can used to hold the pending nodes that do not hold any data. milvus_client.create_resource_group(name=_PENDING_NODES_RESOURCE_GROUP, config=ResourceGroupConfig( requests={"node_num": 0}, # this resource group can hold 0 nodes, no data will be load on it. limits={"node_num": 10000}, # this resource group can hold at most 10000 nodes )) # update default resource group, which can used to hold the nodes that all initial node in it. milvus_client.update_resource_groups({ "__default_resource_group": ResourceGroupConfig( requests={"node_num": node_num}, limits={"node_num": node_num}, transfer_from=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], # recover missing node from pending resource group at high priority. transfer_to=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], # recover redundant node to pending resource group at low priority. )}) milvus_client.create_resource_group(name="rg1", config=ResourceGroupConfig( requests={"node_num": 0}, limits={"node_num": 0}, transfer_from=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], transfer_to=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], )) milvus_client.create_resource_group(name="rg2", config=ResourceGroupConfig( requests={"node_num": 0}, limits={"node_num": 0}, transfer_from=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], transfer_to=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], )) init_cluster(1)利用上述範例程式碼,我們建立了一個名為__pending_nodes 的資源群組,用以存放額外的 QueryNode。我們也建立兩個名為rg1和rg2 的使用者專用資源群組。此外,我們確保其他資源群組會優先從__pending_nodes 中恢復缺失或冗餘的 QueryNode。
叢集水平擴展
假設我們有以下擴展函式:
def scale_to(node_num: int): # scale the querynode number in Milvus into node_num. pass我們可以透過 API 將特定資源群組擴展至指定數量的 QueryNodes,且不會影響其他資源群組。
# scale rg1 into 3 nodes, rg2 into 1 nodes milvus_client.update_resource_groups({ "rg1": ResourceGroupConfig( requests={"node_num": 3}, limits={"node_num": 3}, transfer_from=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], transfer_to=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], ), "rg2": ResourceGroupConfig( requests={"node_num": 1}, limits={"node_num": 1}, transfer_from=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], transfer_to=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], ), }) scale_to(5) # rg1 has 3 nodes, rg2 has 1 node, __default_resource_group has 1 node.叢集縮減
同樣地,我們可以建立縮減規則,優先從__pending_nodes資源群組中選取查詢節點。此資訊可透過
describe_resource_groupAPI 取得,藉此達成縮減指定資源群組的目標。# scale rg1 from 3 nodes into 2 nodes milvus_client.update_resource_groups({ "rg1": ResourceGroupConfig( requests={"node_num": 2}, limits={"node_num": 2}, transfer_from=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], transfer_to=[{"resource_group": _PENDING_NODES_RESOURCE_GROUP}], ), }) # rg1 has 2 nodes, rg2 has 1 node, __default_resource_group has 1 node, __pending_nodes has 1 node. scale_to(4) # scale the node in __pending_nodes
資源群組與多個複本的互動方式
- 單一集合的副本與資源群組之間具有 N 對 N 的關係。
- 當單一集合的多個副本被載入到同一個資源群組時,該資源群組的 QueryNodes 會均勻分佈於各副本之間,確保每個副本擁有的 QueryNodes 數量差異不超過 1。
下一步
若要部署多租戶 Milvus 實例,請參閱以下內容: