milvus-logo
LFAI
首页
  • 概念

时间同步

本主题介绍 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 应该能够看到

  • 一个空的集合C0t2.

  • 数据A1 ,网址t7

  • 数据A1A2 均位于t12

  • 只有t17 上的数据A2 (因为在此之前,数据A1 已从集合中删除)。

当只有一个节点时,这种理想情况很容易实现。但是,Milvus 是一个分布式向量数据库,为了确保不同节点中的所有 DML 和 DDL 操作都能保持有序,Milvus 需要解决以下两个问题:

  1. 上面例子中的两个用户如果在不同的节点上,他们的时间时钟是不同的。例如,如果用户 2 比用户 1 晚 24 小时,那么用户 1 的所有操作在第二天之前都不会被用户 2 看到。

  2. 可能存在网络延迟。如果用户 2 在t17 上对集合C0 进行搜索,Milvus 应能保证t17 之前的所有操作都被成功处理并完成。如果t15 上的删除操作因网络延迟而延迟,那么用户 2 在t17 上进行搜索时,很可能仍能看到本应删除的数据A1

因此,Milvus 采用了时间同步系统(timetick)来解决这些问题。

时间戳甲骨文(TSO)

为了解决上一节提到的第一个问题,Milvus 和其他分布式系统一样,提供了时间戳甲骨文(TSO)服务。这意味着 Milvus 中的所有事件都必须分配一个来自 TSO 而不是本地时钟的时间戳。

TSO 服务由 Milvus 的根协调器提供。客户端可以在单个时间戳分配请求中分配一个或多个时间戳。

TSO 时间戳是一种uint64 值,由物理部分和逻辑部分组成。下图展示了时间戳的格式。

TSO_Timestamp TSO_Timestamp.

如图所示,开头的 46 位是物理部分,即以毫秒为单位的 UTC 时间。最后 18 位是逻辑部分。

时间同步系统(timetick)

本节以数据插入操作为例,解释 Milvus 的时间同步机制。

当代理收到 SDK 的数据插入请求时,它会根据主键的哈希值将插入信息分成不同的信息流 (MsgStream) 。

每条插入信息 (InsertMsg) 在发送到MsgStream 之前都会被分配一个时间戳。

MsgStream Timesync_proxy_ins 是消息队列的封装器,在 Milvus 2.0 中默认为 Pulsar。

timesync_proxy_insert_msg timesync_proxy_insert_msg

一般原则是,在MsgStream 中,来自同一代理的InsertMsgs 的时间戳必须是递增的。但是,来自不同代理的InsertMsgs 的时间戳却没有这样的规则。

下图是InsertMsgsMsgStream 中的示例。该代码段包含五个InsertMsgs ,其中三个来自Proxy1 ,其余来自Proxy2

msgstream msgstream

来自Proxy1 的三个InsertMsgs 的时间戳是递增的,来自Proxy2 的两个InsertMsgs 的时间戳也是递增的。但是,Proxy1Proxy2 InsertMsgs 之间没有特定的顺序。

Proxy1 一种可能的情况是,当从Proxy2 读取时间戳为110 的信息时,Milvus 发现时间戳为80 的信息仍在MsgStream 中。因此,Milvus 引入了时间同步系统 timetick,以确保从MsgStream 读取信息时,必须消耗掉所有时间戳值较小的信息。

time_synchronization 时间同步

如上图所示、

  • 每个代理定期(默认情况下每 200 毫秒)向根协调器报告MsgStream中最新InsertMsg 的最大时间戳值。

  • 根协调器会识别该Msgstream 上的最小时间戳值,无论该InsertMsgs 属于哪个代理。然后,根协调器将这个最小时间戳插入Msgstream 。这个时间戳也称为 timetick。

  • 当消费者组件读取根协调器插入的时间戳时,它们就会明白所有时间戳值较小的插入信息都已被消耗。因此,可以在不中断订单的情况下安全地执行相关请求。

下图是Msgstream 插入时间刻度的示例。

timetick 时间戳

MsgStream 根据时间刻度分批处理报文,以确保输出的报文符合时间戳的要求。

下一步

翻译自DeepLogo

反馈

此页对您是否有帮助?