🚀 Zilliz Cloudを無料で試す、完全管理型のMilvus—10倍の高速パフォーマンスを体験しよう!今すぐ試す>>

milvus-logo
LFAI
  • Home
  • Blog
  • ベクターデータベースにおけるデータ挿入とデータ永続化

ベクターデータベースにおけるデータ挿入とデータ永続化

  • Engineering
April 06, 2022
Bingyi Sun

Cover image 表紙画像

この記事はBingyi Sunが執筆し、Angela Niがトランスコードしたものです。

前回のDeep Diveシリーズでは、世界で最も先進的なベクトル・データベースであるMilvusでデータがどのように処理されるかを紹介した。今回は引き続き、データ挿入に関わるコンポーネントを検証し、データモデルを詳細に説明し、Milvusでどのようにデータの永続化が実現されているかを説明する。

ジャンプ

Milvusアーキテクチャのまとめ

Milvus architecture. milvusのアーキテクチャ。

SDKはロードバランサーを介してポータルであるプロキシにデータ要求を送信します。その後、プロキシはコーディネータサービスと対話し、DDL(データ定義言語)およびDML(データ操作言語)リクエストをメッセージストレージに書き込みます。

クエリーノード、データノード、インデックスノードを含むワーカーノードは、メッセージストレージからリクエストを消費する。具体的には、クエリーノードはデータクエリーを担当し、データノードはデータ挿入とデータ永続化を担当し、インデックスノードは主にインデックス構築とクエリーアクセラレーションを担当する。

最下層はオブジェクトストレージで、主にMinIO、S3、AzureBlobを活用してログ、デルタビンログ、インデックスファイルを保存する。

データ挿入リクエストのポータル

Proxy in Milvus. MilvusのProxy。

Proxyはデータ挿入リクエストのポータルとして機能する。

  1. 最初に、プロキシはSDKからのデータ挿入要求を受け付け、ハッシュアルゴリズムを用いてそれらの要求をいくつかのバケットに振り分ける。
  2. 次にプロキシはデータコーデックにMilvusの最小単位であるセグメントを割り当てるよう要求する。
  3. その後、プロキシは要求されたセグメントの情報をメッセージストアに挿入し、これらの情報が失われないようにする。

データコーディネータとデータノード

データコーディネートの主な機能はチャネルとセグメントの割り当てを管理することであり、データノードの主な機能は挿入されたデータを消費し、永続化することである。

Data coord and data node in Milvus. Milvusにおけるデータコーディネータとデータノード

機能

データ・コーディネートは以下のような役割を果たす:

  • セグメントスペースの割り当てプロキシがセグメント内の空きスペースを使用してデータを挿入できるように、データコーディネータはプロキシに成長しているセグメント内のスペースを割り当てる。

  • データコーデックによって割り当てられた各セグメント内のスペースは永続的ではないため、データコーデックは各セグメント割り当ての有効期限も記録しておく必要がある。

  • セグメント・データを自動的にフラッシュするセグメントがいっぱいになると、データ・コーデックは自動的にデータ・フラッ シュをトリガーする。

  • データノードにチャネルを割り当てるコレクションは複数のvchannelsを持つことができます。データ・コーデックは、どのvchannelsがどのデータ・ノードによって消費されるかを決定します。

データノードは以下の役割を果たします:

  • データの消費データ・ノードはデータ・コーデックによって割り当てられたチャネルからデータを消費し、データ のシーケンスを作成します。

  • データの永続性挿入されたデータをメモリにキャッシュし、データ量がある閾値に達すると、挿入されたデータをディスクに自動フラッシュする。

ワークフロー

One vchannel can only be assigned to one data node. 1つのvchannelは1つのデータ・ノードにのみ割り当てることができる

上の画像に示すように、コレクションには4つのvchannel(V1、V2、V3、V4)があり、2つのデータノードがあります。データ・コーディネータは1つのデータ・ノードにV1とV2のデータを消費させ、もう1つのデータ・ノードにV3とV4のデータを消費させる可能性が高い。1つのvchannelを複数のデータ・ノードに割り当てることはできないが、これはデータ消費の繰り返しを防ぐためであり、そうしないと同じセグメントに同じバッチが繰り返し挿入されることになる。

ルート・コーディネーションとタイムティック

ルート・コーデックはTSO(タイムスタンプ・オラクル)を管理し、タイムティック・メッセージをグローバルに発行する。各データ挿入リクエストには、ルート・コーデックによってタイムスタンプが割り当てられる。タイムティックはMilvusの要であり、Milvusの時計のような役割を果たし、Milvusシステムがどの時点にあるかを示します。

Milvusにデータが書き込まれる際、各データ挿入要求にはタイムスタンプが付与されます。データ消費時、各タイムデータノードはタイムスタンプが一定の範囲内にあるデータを消費する。

An example of data insertion and data consumption based on timestamp. タイムスタンプに基づくデータ挿入とデータ消費の例

上の画像はデータ挿入のプロセスです。タイムスタンプの値は1,2,6,5,7,8の数字で表される。データはp1とp2の2つのプロキシによってシステムに書き込まれる。データ消費中、タイム・ティックの現在時刻が5の場合、データ・ノードはデータ1と2のみを読み取ることができる。次に、2回目の読み取り時に、タイムティックの現在時刻が9になると、データノードによってデータ6,7,8を読み取ることができます。

データ構成:コレクション、パーティション、シャード(チャンネル)、セグメント

Data organization in Milvus. Milvusにおけるデータ構成。

まずこの記事を読んで、Milvusのデータモデルとコレクション、シャード、パーティション、セグメントの概念を理解しよう。

要約すると、Milvusにおける最大のデータ単位はコレクションであり、これはリレーショナルデータベースのテーブルに例えることができます。コレクションは複数のシャード(それぞれがチャネルに対応する)と、各シャード内の複数のパーティションを持つことができる。上の図に示すように、チャンネル(シャード)は縦棒であり、パーティションは横棒である。それぞれの交点にあるのがセグメントという概念で、データ割り当ての最小単位である。Milvusでは、インデックスをセグメント上に構築する。Milvusシステムはクエリ中、異なるクエリノードにおけるクエリ負荷のバランスをとるが、このプロセスはセグメントという単位に基づいて行われる。セグメントには複数のビンログが含まれており、セグメントデータが消費されるとビンログファイルが生成されます。

セグメント

Milvusのセグメントには、gloing、sealed、flushedの3種類があり、それぞれステータスが異なります。

成長セグメント

グローイングセグメントは、データ挿入のためにプロキシに割り当てられる新しく作成されたセグメントです。セグメントの内部空間は、使用済み、割り当て済み、または空きである。

Three status in a growing segment 成長セグメントの3つのステータス

  • 使用済み:使用済み:成長セグメントの空間のこの部分は、データノードによって消費された。
  • 割り当て済み(Allocated): プロキシによって要求され、データノードによって割り当てられた。割り当てられた領域は、一定時間後に期限切れとなる。
  • Free: 成長セグメントのこの部分は使用されていない。空き領域の値は、セグメント全体の領域から使用済み領域と割り当て済み領域の値を引いたものに等しい。そのため、セグメントの空き領域は、割り当てられた領域が期限切れになるにつれて増えていく。

密閉されたセグメント

封印されたセグメントとは、データ挿入のためにプロキシに割り当てられなくなった閉じたセグメントのことである。

Sealed segment in Milvus Milvusにおけるクローズドセグメント

以下の場合、成長セグメントは封印されます:

  • 成長セグメントの使用領域が全領域の75%に達した場合、セグメントは封印されます。
  • Milvusユーザが手動でFlush()を呼び出し、コレクション内のすべてのデータを永続化する。
  • 成長セグメントが多すぎると、データノードがメモリを過剰に消費するためです。

フラッシュセグメント

フラッシュされたセグメントとは、すでにディスクに書き込まれたセグメントのことである。フラッシュとは、データの永続化のためにセグメントデータをオブジェクトストレージに保存することです。セグメントをフラッシュできるのは、密閉されたセグメントで割り当てられた領域がなくなったときだけです。フラッシュされると、封印されたセグメントはフラッシュされたセグメントとなる。

Flushed segment in Milvus Milvusにおけるフラッシュセグメント

チャンネル

チャネルの割り当て

  • データノードの起動またはシャットダウン時
  • プロキシによってセグメント領域が要求されたとき。

チャネル割り当てにはいくつかの戦略があります。Milvusはそのうちの2つをサポートしています:

  1. 一貫性ハッシュ

Consistency hashing in Milvus Milvusの一貫性ハッシング

Milvusのデフォルト戦略。この戦略では、ハッシュ技術を利用して各チャネルにリング上の位置を割り当て、クロック方向に検索してチャネルに最も近いデータノードを見つける。したがって、上の図では、チャネル1はデータ・ノード2に割り当てられ、チャネル2はデータ・ノード3に割り当てられている。

しかし、この戦略の1つの問題点は、データ・ノード数の増減(新しいデータ・ノードの開始やデータ・ノードの突然のシャットダウンなど)がチャネル割り当てプロセスに影響を与える可能性があることです。この問題を解決するために、データ・コーディネートはetcdを介してデータ・ノードのステータスを監視し、データ・ノードのステータスに変更があった場合にデータ・コーディネートに即座に通知できるようにする。そしてデータ・コーディネートはさらに、どのデータ・ノードにチャンネルを適切に割り当てるかを決定する。

  1. ロードバランシング

第2の戦略は、同じコレクションのチャンネルを異なるデータノードに割り当て、チャンネルが均等に割り当てられるようにすることです。この戦略の目的はロードバランスを達成することである。

データ割り当て:いつ、どのように

The process of data allocation in Milvus Milvusのデータ割り当てプロセス

データ割り当てのプロセスはクライアントから始まる。まず、タイムスタンプ(t1 )を持つデータ挿入リクエストをプロキシに送信する。次に、プロキシはデータコーディネイトにセグメント割り当て要求を送る。

セグメント割り当て要求を受信すると、データ コーダーはセグメントの状態をチェックし、セグメントを割り当てる。作成されたセグメントの現在のスペースが、新しく挿入されたデータ行に十分であれば、データ コーダーはそれらの作成されたセグメントを割り当てる。しかし、現在のセグメントで使用可能なスペースが十分でない場合は、 データ コーダーは新しいセグメントを割り当てる。データ・コーデックは、リクエストごとに 1 つ以上のセグメントを返すことができる。その間に、データコーデ ィネートは割り当てられたセグメントをメタサーバーに保存し、データを永続化する。

その後、データ コーダーは割り当てられたセグメントの情報(セグメントID、行数、有効期限t2 など)をプロキシに返す。プロキシは、割り当てられたセグメントの情報をメッセー ジストアに送信し、これらの情報が適切に記録されるようにする。t1 の値は、t2 の値よりも小さくなければならないことに注意。t2 のデフォルト値は2,000ミリ秒であり、data_coord.yaml ファイルのパラメータsegment.assignmentExpiration を設定することで変更できる。

Binlogファイル構造とデータの永続性

Data node flush データノードのフラッシュ

データ・ノードはメッセージ・ストアをサブスクライブします。これは、データ挿入要求がメッセージ・ストアに保持され、データ・ノードが挿入メッセージを消費できるためです。データノードは最初に挿入要求を挿入バッファに置き、要求が蓄積されると、閾値に達した後にオブジェクトストレージにフラッシュされます。

Binlogファイル構造

Binlog file structure. Binlogファイル構造

MilvusのBinlogファイル構造はMySQLのそれと似ています。Binlogはデータ復旧とインデックス構築の2つの機能を果たすために使用されます。

ビンログには多くのイベントが含まれます。各イベントにはイベントヘッダとイベントデータがあります。

イベントヘッダには、ビンログ作成時刻、書き込みノードID、イベント長、NextPosition(次のイベントのオフセット)などのメタデータが書き込まれます。

イベントデータは固定と可変の2つに分けられる。

File structure of an insert event. 挿入イベントのファイル構造

INSERT_EVENT のイベント・データの固定部分には、StartTimestampEndTimestampreserved が含まれる。

可変部分には、挿入されたデータが格納される。挿入データはパーケット形式に配列され、このファイルに格納される。

データの永続化

スキーマに複数のカラムがある場合、milvusはカラムにビンログを格納します。

Binlog data persistence. ビンログデータの永続性

上の図のように、最初のカラムは主キーbinlogです。2番目のカラムはタイムスタンプカラムです。残りはスキーマで定義されたカラムです。MinIOのbinlogのファイルパスも上の画像に示されています。

ディープダイブシリーズについて

Milvus 2.0の一般提供の正式発表に伴い、Milvusのアーキテクチャとソースコードの詳細な解釈を提供するために、このMilvus Deep Diveブログシリーズを企画しました。このブログシリーズで扱うトピックは以下の通りです:

Like the article? Spread the word

続けて読む