時刻同期
このトピックでは、Milvusの時刻同期メカニズムについて紹介します。
概要
Milvusのイベントは一般的に2つのタイプに分類することができます:
データ定義言語 (DDL) イベント: コレクションの作成/削除、パーティションの作成/削除など。
データ操作言語(DML)イベント: 挿入、検索など。
DDLイベントであれDMLイベントであれ、どのイベントにも、このイベントがいつ発生したかを示すタイムスタンプが付けられます。
Milvus の一連の DML および DDL イベントを以下の表に示す時間順で開始する 2 人のユーザがいるとします。
タイムスタンプ | ユーザ 1 | ユーザ 2 |
---|---|---|
t0 | C0 という名前のコレクションを作成した。 | / |
t2 | / | コレクションC0 を検索。 |
t5 | データA1 をコレクションに挿入C0 . | / |
t7 | / | コレクションC0 を検索。 |
t10 | データA2 をコレクションに挿入C0 . | / |
t12 | / | コレクションを検索C0 |
t15 | コレクションからデータA1 を削除C0 . | / |
t17 | / | コレクションを検索C0 |
理想的には、ユーザー2は以下を見ることができる:
空のコレクション
C0
att2
.t7
にあるデータA1
。t12
のデータA1
とA2
の両方。t17
のデータA2
のみ(この時点より前に、データA1
がコレクションから削除されているため)。
この理想的なシナリオは、ノードが1つしかない場合には容易に達成できる。しかし、Milvusは分散ベクタデータベースであり、異なるノードにおけるすべてのDMLおよびDDL操作が整然と保たれるように、Milvusは以下の2つの問題に対処する必要がある:
上の例の2人のユーザが異なるノードにいる場合、タイムクロックが異なります。例えば、ユーザ 2 がユーザ 1 より 24 時間遅れている場合、ユーザ 1 によるすべての操作は翌日までユーザ 2 には見えません。
ネットワーク遅延が発生する可能性もあります。ユーザ2がコレクション
C0
、t17
で検索を行った場合、Milvusはt17
以前のすべての操作が正常に処理され完了することを保証できるはずです。t15
での削除操作がネットワーク遅延のために遅延した場合、ユーザ2がt17
で検索を行う際に、削除されたはずのデータA1
をまだ見ることができる可能性が非常に高い。
そこでMilvusでは、この問題を解決するために時刻同期システム(timetick)を採用している。
タイムスタンプ・オラクル(TSO)
前節で述べた最初の問題を解決するために、Milvusは他の分散システム同様、タイムスタンプオラクル(TSO)サービスを提供している。つまり、Milvusのすべてのイベントはローカルクロックからではなく、TSOからのタイムスタンプで割り当てられなければならない。
TSOサービスはMilvusのルートコーディネーターによって提供される。クライアントは1つのタイムスタンプ割り当てリクエストで1つ以上のタイムスタンプを割り当てることができます。
TSOタイムスタンプは物理的な部分と論理的な部分で構成されるuint64
。下図はタイムスタンプのフォーマットを示している。
TSO_Timestamp。
図示されているように、先頭の46ビットは物理的な部分、すなわちミリ秒単位のUTC時間である。最後の18ビットは論理部分である。
時刻同期システム(timetick)
ここではデータ挿入操作を例に、Milvusの時刻同期機構を説明する。
プロキシはSDKからデータ挿入要求を受け取ると、主キーのハッシュ値に従って挿入メッセージを異なるメッセージストリーム(MsgStream
)に分割する。
各挿入メッセージ(InsertMsg
)はMsgStream
に送信される前にタイムスタンプが割り当てられる。
MsgStream
はメッセージ・キューのラッパーであり、Milvus 2.0ではデフォルトでPulsarとなっている。timesync_proxy_insert_msg
一般的な原則の1つは、MsgStream
、同じプロキシからのInsertMsgs
のタイムスタンプはインクリメンタルでなければならないということである。しかし、異なるプロキシからのInsertMsgs
のタイムスタンプにはそのようなルールはない。
以下の図は、MsgStream
の中のInsertMsgs
の例である。このスニペットには5つのInsertMsgs
が含まれ、そのうちの3つはProxy1
からのもので、残りはProxy2
からのものである。
msgstream
Proxy1
からの3つのInsertMsgs
のタイムスタンプはインクリメンタルであり、Proxy2
からの2つのInsertMsgs
もインクリメンタルである。しかし、Proxy1
とProxy2
InsertMsgs
の間には特定の順序はない。
考えられるシナリオとしては、Proxy2
からのタイムスタンプ110
のメッセージを読むときに、Proxy1
からのタイムスタンプ80
のメッセージがまだMsgStream
の中にあることをMilvusが発見することです。したがって、Milvusは、MsgStream
からのメッセージを読むときに、タイムスタンプ値の小さいメッセージはすべて消費されなければならないことを保証するために、timetickという時間同期システムを導入しています。
時間同期
上の図に示すように
各プロキシは、定期的(デフォルトでは200ミリ秒ごと)に、
MsgStream
の最新のInsertMsg
の最大のタイムスタンプ値をroot coordに報告する。ルートコーデ ィックは、
InsertMsgs
がどのプロキシに属していても、このMsgstream
の最小タイムスタンプ値を特定する。それからルートコーデ ィックは、この最小タイムスタンプをMsgstream
。 このタイムスタンプはtimetickとも呼ばれる。コンシューマーコンポーネントがルートコー ディネートによって挿入されたタイムスティックを読むとき、コンシューマー コンポーネントは、より小さいタイムスタンプ値を持つすべての挿入メッセー ジが消費されたことを理解する。したがって、関連するリクエストは、オー ダーを中断することなく安全に実行できる。
以下の図は、タイムティックが挿入されたMsgstream
の例である。
タイムティック
MsgStream
は、出力メッセージがタイムスタンプの要件を満たすように、タイムティックに従ってバッチでメッセージを処理します。
次のページ
- タイムスタンプの概念について学ぶ。
- Milvusのデータ処理ワークフローについて学ぶ。