Sources 和 Mirrors 复制机制

当一个流被配置为sourcemirror时,它会自动且异步地从原始流复制消息。

译者注:在本文中,关于 设置了 Sources 的流(英文原文 source streams):我没找到好的译法,就把它直译为 被配置了 source 的流 了。翻译AI对 origin stream、source streams 给出的都是相同的 “源流”,但他们两个指向的不是一个东西:origin stream 代表作为数据来源的原始流;而 source 在这里是 表达这个流被配置为源源不断地 "从(某地)获取" 数据,它是动词,“源流”的话根本没有表达出动词的意思,而且会导致和 原始流 概念相混淆,所以我没有通过AI的翻译。而现在这种直译虽然长,但能保证概念的准确传递,消除误解。大家可以来贡献更好的翻译!(详见 zh-cn/ZHCN-DOCS-FEEDBACK.md#术语表 )

sourcemirror设计为具有鲁棒性,并能从连接中断中恢复。它们适用于高延迟和不可靠连接的地理分布场景。例如,即使是一个间歇性启动、每隔几天连接一次的叶子节点,仍然可以通过 设置了 Sources 的流/镜像流 链接接收或发送消息。
另一个使用场景是当跨账户连接流时。

客户端在声明配置时,有几种可用选项。

  • Name - 原始流的名称,用于从中获取消息。
  • StartSeq - 可选的原始流起始序列号,用于开始镜像。
  • StartTime - 可选的消息起始时间,用于开始镜像。任何等于或大于该起始时间的消息都将被包含。
  • FilterSubject - 可选的主题过滤,用来使流仅包括匹配这些主题的消息(通常包含通配符)。注意,此选项不能与SubjectTransforms一起使用。
  • SubjectTransforms - 可选的一组主题转换,会在从原始流获取消息时应用。请注意,在这种情况下,Source 选项将被用作过滤原始流上的主题,而 Destination 可选地提供以设置转换。由于可以使用多个主题转换,因此可以从原始流中获取不相交的主题,同时保持消息的顺序。注意,此选项不能与FilterSubject一起使用。
  • Domain - 原始流所在JetStream域的可选值。这通常用于中心集群和叶子节点拓扑结构中。

被配置为使用源或镜像的流可以有自己的保留策略、复制和存储类型。

{% hint style="info" %}

  • 对于使用源或镜像的流所做的更改(例如删除消息或发布),不会反映回数据来源(原始流)。
  • 类似地,在原始流中进行的删除操作不会通过sourcemirror协议扩散到目标流。 {% endhint %}

{% hint style="info" %} Sources是对Mirror的泛化,允许同时从一个或多个流中获取数据。
如果你想要目标流作为只读副本使用:

  • 配置流时让它不监听主题
  • 或者通过客户端授权临时让它停止监听主题。 {% endhint %}

一般情况下

  • 所有配置都在接收端完成。无需对数据来源和镜像的流进行配置。如果接收方消失,源端无需做任何调整。
  • 一个流可以作为多个流的源(source)。这对于地理分布或设计“扇出”拓扑结构非常有用,其中数据需要可靠地分发到大量(最多数百万)的客户端连接。
  • 通过 API prefix 明确支持叶子节点和叶子节点域。

对于 设置了 Sources 的流

定义了 Sources 的流是一种通用的复制机制,它允许同时从一个或多个流中获取数据。设置了 Sources 的流仍可当作正常的流使用,允许本地客户端直接写入或发布到该流。本质上,设置了 Sources 的流和本地客户端的写入会被聚合为一个单一的交错流。
把主题转换和过滤功能相结合, Sources 选项允许你设计复杂的分布式数据架构!

{% hint style="info" %} 设置了 Sources 的流在从原始流获取消息时不会保留序列号,但会保留消息在流中的顺序。在指向同一目标的不同原始流之间,消息的顺序是未定义的。 {% endhint %}

对于 镜像流

镜像流只能从一个确切的流中获取消息,客户端无法直接向镜像流写入。尽管客户端不能直接向镜像流发布消息,但消息可以按需删除(若超出保留策略),并且消费者在常规流上拥有所有可用功能。

{% hint style="info" %}

在边缘部署下的预期行为

  • Source 和 Mirror 的 协议设计初衷是(地理上的)单向数据复制。所以 这两种配置均不保证流之间的完全同步,包括删除操作或其他流属性的复制。
  • 从 设置了 Sources 的流 或 镜像流 中提取内容的流应保持相对稳定。如果在发布消息后快速删除消息,可能会由于复制过程的异步特性而导致复制不一致。
  • 设置了 Sources 的流 和 镜像流 会尝试高效地复制消息,并对原始流暂时无法访问的情况(甚至长时间)保持宽容,例如在使用间歇性连接的叶子节点时。为了提高效率,断开连接后的恢复间隔为10-20秒。
  • Source 和 Mirror 的协议 不会在原始流中创建可见的消费者。

对于 WorkQueue 保留策略

设置了 Sources 的流 或 镜像流,在与采用 WorkQueuePolicy 的原始流配合工作时,其功能语境较为有限。此时,目标流将扮演一个消费者的角色,从原始流中移除(消费)消息。

然而,当通过间歇性连接的叶子节点进行操作时,该实现的健壮性不足。不过在目标流(即设置了 source/mirror 的流)位于同一集群内部的情况下,它通常能良好运行。

{% hint style="warning" %} 仅部分支持 给 设置了 Sources 的流、镜像流 设定 使用 WorkQueuePolicy 的原始流。它无法有效应对叶子节点连接中断的情况。

因为,从远程原始流拉取消息的内部消费者并非持久化的。因此,当叶节点连接断开时,其他客户端可能消费并确认消息,导致这些消息从工作队列中被移除,从而造成数据丢失。 {% endhint %}

{% hint style="warning" %} 如果 您正尝试在 使用 WorkQueuePolicy 的原始流 上创建额外的(冲突的)消费者,则其行为将变得未定义。 一个使用 WorkQueuePolicy 的流仅允许每个主题有一个消费者。 如果 设置了 Sources 的流/镜像流 与这种原始流之间的连接处于活动状态,那本地客户端在这种流上尝试为相同主题创建消费者时将会失败。反之,如果原始流上已存在消费相同主题的本地消费者,则无法成功创建 设置了 Sources 的流/镜像流。 (译注:Sources/Mirrors 机制会在原始流上创建一个“隐形”的消费者来获取消息。此消费者与显式创建的消费者会竞争同一主题的消息,从而违反工作队列的语义。 ) {% endhint %}

对于 基于兴趣的保留策略

{% hint style="warning" %} 基于兴趣的 设置了 Sources 的流/镜像流 不受支持。Jetstream 并未禁止这种配置,但这样配置后它会产生什么行为是未定义的,未来可能会发生变化。 {% endhint %}