時間同步
本主題介紹 Milvus 的時間同步機制。
概述
Milvus 中的事件一般可分為兩種類型:
資料定義語言 (DDL) 事件:建立/刪除集合、建立/刪除分割區等。
資料操作語言 (DML) 事件:插入、搜尋等。
任何事件,不論是 DDL 或 DML 事件,都標有時間戳記,可以指出事件發生的時間。
假設有兩個使用者在 Milvus 發起一系列 DML 和 DDL 事件,時間順序如下表所示。
| 時間戳記 | 使用者 1 | 使用者 2 |
|---|---|---|
| t0 | 建立了一個名為C0. | / |
| t2 | / | 在資料集中進行搜尋C0. |
| t5 | 插入資料A1 到資料庫C0. | / |
| t7 | / | 在資料集中進行搜尋C0. |
| t10 | 插入資料A2 到資料庫C0. | / |
| t12 | / | 在資料集中進行搜尋C0 |
| t15 | 從資料集中刪除資料A1 C0 . | / |
| t17 | / | 在資料集中進行搜尋C0 |
理想情況下,使用者 2 應該可以看到
一個空的集合
C0在t2.資料
A1在t7.資料
A1和A2均位於t12。只有資料
A2att17(因為資料A1在此點之前已從集合中刪除)。
當只有一個單一節點時,這種理想的情況很容易實現。然而,Milvus 是分散式向量資料庫,為了確保不同節點中的所有 DML 與 DDL 作業都能保持順序,Milvus 需要解決以下兩個問題:
如果上面例子中的兩個使用者在不同的節點上,他們的時間時鐘是不同的。例如,如果使用者 2 比使用者 1 晚 24 小時,那麼使用者 1 的所有作業要到第二天才會被使用者 2 看見。
可能存在網路延遲。如果使用者 2 在
t17對資料集C0進行搜尋,Milvus 應該可以保證t17之前的所有作業都成功處理並完成。如果在t15的刪除作業因為網路延遲而延遲,使用者 2 在t17進行搜尋時,很有可能仍然可以看到應該被刪除的資料A1。
因此,Milvus 採用時間同步系統 (timetick) 來解決問題。
時間戳oracle (TSO)
為了解決上一節提到的第一個問題,Milvus 和其他分散式系統一樣,提供時間戳oracle (TSO) 服務。這表示 Milvus 中的所有事件都必須從 TSO 而非本機時鐘分配時間戳。
TSO 服務由 Milvus 的根協調器提供。用戶端可以在單個時間戳分配請求中分配一個或多個時間戳。
TSO 時間戳是一種uint64 值,由物理部分和邏輯部分組成。下圖展示了時間戳的格式。
TSO_Timestamp.
如圖所示,開頭的 46 位元是實體部分,也就是以毫秒為單位的 UTC 時間。最後的 18 位元是邏輯部分。
時間同步系統 (timetick)
本節以資料插入操作為例,說明 Milvus 的時間同步機制。
當 proxy 收到 SDK 的資料插入請求時,會依照主鍵的哈希值將插入訊息分成不同的訊息流 (MsgStream)。
每條插入訊息 (InsertMsg) 在傳送到MsgStream 之前,都會被指定一個時間戳。
MsgStream 是訊息佇列的包裝,在 Milvus 2.0 預設是 Pulsar。
timesync_proxy_insert_msg
一個一般原則是,在MsgStream, 來自同一個 proxy 的InsertMsgs 的時間戳必須是遞增的。但是,對於來自不同代理的InsertMsgs ,則沒有這樣的規則。
下圖是InsertMsgs 在MsgStream 中的範例。該片段包含五個InsertMsgs ,其中三個來自Proxy1 ,其餘來自Proxy2 。
msgstream
來自Proxy1 的三個InsertMsgs 的時間戳是遞增的,來自Proxy2 的兩個InsertMsgs 的時間戳也是遞增的。但是,Proxy1 和Proxy2 InsertMsgs 之間沒有特定的順序。
一種可能的情況是,當從Proxy2 讀取時間戳為110 的訊息時,Milvus 發現時間戳為80 的訊息仍在Proxy1 的MsgStream 中。因此,Milvus 引進了時間同步系統 timetick,以確保從MsgStream 讀取訊息時,必須消耗所有時間戳值較小的訊息。
時間同步
如上圖所示、
每個代理定期(預設為每 200 ms)將
MsgStream中最新InsertMsg的最大時間戳值報告給根坐標。無論
InsertMsgs屬於哪個代理伺服器,Root Coord 都會找出此Msgstream的最小時間戳值。然後,root coord 將這個最小時間戳插入Msgstream。這個時間戳也稱為 timetick。當消費者元件讀取由根坐標插入的 timetick 時,它們會了解所有時間戳值較小的插入訊息已被消耗。因此,可以在不中斷訂單的情況下安全地執行相關請求。
下圖是Msgstream 插入時間刻度的範例。
時間標記
MsgStream 會根據時間刻度分批處理訊息,以確保輸出訊息符合時間戳記的要求。在上面的範例中,它會在Timestamp: 120 消耗除了Proxy2 的InsertMsgs 以外的所有記錄,因為它是在最新的 TimeTick 之後。