首页 > 解决方案 > NATS Jetstream 是否通过密钥提供消息排序?

问题描述

我是 NATS Jetstream 的新手,我一直在阅读他们的官方文档 ( https://docs.nats.io/jetstream/jetstream ) 以了解其概念并将其与 Kafka 进行比较。我拥有的主要用例之一是解决基于特定 id 的消息/事件排序(如partition keyKafka 世界中的 a )。

例如,一个实体有几个更新事件,我的系统需要以相同的顺序Order使用特定的事件。Order在这种情况下,我会order-id在发布到 Kafka 主题时将其用作分区键。我如何在 Jetstream 中做到这一点?

我在 Jetstream 中遇到过重复数据删除键 ( Nats-Msg-Id),但我认为此功能更类似于 Kafka 中的主题压缩。我对吗?

尽管如此,我还是用 Golang 编写了以下代码进行发布:

order = Order{
    OrderId: orderId,
    Status:  status,
}
orderJson, _ := json.Marshal(order)
dedupKey := nats.MsgId(order.OrderId)
_, err := js.Publish(subjectName, orderJson, dedupKey)

我这样做对吗?特定 orderId 的所有订单是否会转到 Jetstream 世界中消费者组内的同一消费者,从而保持顺序?

编辑 1

这是我从@tbeets 的建议中得到的。例如,我预定义了 10 个流主题,例如ORDER.1, ORDER.2, ORDER.3....ORDER.10

在发布方面,我可以order-id%10+1找到我想要发布的确切流主题。所以在这里,我们已经实现了相同 orderId 的所有更新事件每次都将转到相同的流主题。

现在,在订阅者方面,我有 10 个消费者组(每个消费者组中有 10 个消费者),每个消费者都从一个特定的流主题中消费,比如consumerGroup-1从消费来源ORDER.1consumerGroup-2消费来源ORDER.2等等......

比如说,order-id111 有 2 个订单更新事件,这将被映射到ORDER.1流主题,并相应地consumerGroup-1消耗这 2 个事件。但是在这个consumerGroup中,两个更新事件可以去到不同的消费者,如果其中一个消费者有点忙或有点慢,那么在整体层面上,订单更新事件消费可能不同步或乱序.

Kafka 使用分区键的概念解决了这个问题,因为消费者组的消费者被分配到特定的分区。因此,同一个 orderId 的所有事件都被同一个消费者消费,从而保持订单更新事件消费的顺序。如何在 Jetstream 中解决此问题?

标签: goapache-kafkajetstreamnats.ionats-streaming-server

解决方案


在 NATS 中,您的发布主题可以包含多个分隔标记。因此,例如,您的 Order 事件可以发布到 ORDER.{store}.{orderid} ,其中最后两个令牌特定于每个事件,并提供您的用例所需的任何切片和骰子维度。

然后为 ORDER.> 定义一个 JetStream(即所有事件)。可以在 JetStream 上创建 N 个消费者(临时的或持久的),每个消费者都有一个可选的过滤器定义,以满足您的用例需求(例如 ORDER.Store24.>)在底层流的消息上。JetStream 保证消息(过滤或未过滤)按接收顺序传递。


推荐阅读