谷歌 pubsub 中的订购保证是在确认时还是在到达时执行的?

huangapple go评论65阅读模式
英文:

Are ordering guarantees in Google pubsub enforced upon on acknowledgement or upon arrival?

问题

我有一个启用了订购的订阅,并在主题上排队消息时设置了排序键。在实践中,我在日志中几乎看不到订阅者亲和性的证据。这在技术上并不违反规范,因为对排序键的订阅者亲和性是尽力而为的,但不能保证。

然而,我确实需要保证的是严格排序,以避免在将从有序订阅中读取的数据持久化到数据库时出现锁争用。排序键与数据库锁存在一对一的关系。对于给定的排序键,我不希望在明确确认之前读取下一条消息,无论哪个订阅者消费下一条消息。这样,尽管有多个订阅者共享一个有序订阅,以及由不同订阅者消耗的具有相同排序键的消息,我仍将避免数据库中的锁争用,这在当前的生产环境中是一个非常真实的问题。

(我应该注意,在我的情况下,我不能使用消息属性,因为pubsub不允许动态过滤,并且具有订阅者的节点数量是动态自动缩放的,而不是确定性的。因此,通过模数除法将消息属性映射到订阅者不是一个选项)

我知道我不是第一个为此目的使用排序键的人: https://stackoverflow.com/questions/71421419/subscriber-affinity-with-ordering-key-but-without-in-order-delivery

在实践中,我发现订阅者亲和性相当松散。只要我知道对于给定的排序键,新消息将不会被读取,直到明确确认了前一条消息,无论哪个订阅者读取下一条消息。这是否由pubsub保证?如果"message1"和"message2"按顺序排队并具有相同的排序键,在有序订阅上,"message2"在"message1"被读取之前不能被读取,但"message2"能在"message1"被确认之前被读取吗?

英文:

I have a subscription with ordering enabled and I am setting an ordering key when enqueuing messages on a topic. In practice I see very little evidence of subscriber affinity in the logs. This does not technically violate the specification as subscriber affinity on an ordering key is best effort, but not guaranteed.

What I do however need to guarantee is strict ordering, to avoid lock contention in my database when persisting data read from an ordered subscription. There is a one-to-one correlation between ordering keys and database locks. For a given ordering key I do not want to read the next message until the previous one has been explicitly acknowledged, regardless of which subscriber consumes the next message. This way despite having an ordered subscription shared by many subscribers, and messages with the same ordering key consumed by different subscribers, I will still avoid lock contention in the database, which is currently a very real problem in production.

(I should note that in my case I cannot use message attributes for this, because pubsub does not allow dynamic filtering, and the number of nodes with subscribers is dynamically autoscaled and not deterministic. Therefore mapping a message attribute to a subscriber via modulo division is not an option)

I know that I am not the first person to use ordering keys for this purpose: https://stackoverflow.com/questions/71421419/subscriber-affinity-with-ordering-key-but-without-in-order-delivery

In practice I found subscriber affinity to be rather loose. I can live with this as long as I know that for a given ordering key a new message will not be read, until the previous message has been acknowledged, regardless of which subscriber reads the next message. Is this guaranteed by pubsub???

If "message1" and "message2" are enqueued in that order and have the same ordering key, on an ordered subscription, "message2" cannot be read until "message1" has been read, but can be "message2" be read before "message1" has been acknowledged???

答案1

得分: 2

Cloud Pub/Sub的订购保证不保证必须在下一条消息交付之前接收确认。当使用Cloud Pub/Sub客户端库时,保证是对于一个订购键的下一条消息将不会在用户指定的回调完成之前交付给用户指定的回调,直到上一条消息完成。如果您始终在回调中确认消息,那么这实际上意味着保证下一条消息不会在上一条消息被确认之前交付。然而,如果异步确认,下一条消息可能会在前一条消息被确认之前交付到您的回调函数。

一般来说,这些传递将发送到相同的订阅者。如果之前的消息没有被确认,应该不可能让不同的订阅者接收后续的消息。然而,请记住,Cloud Pub/Sub具有至少一次传递语义,并且确认截止日期是尽力而为管理的。因此,如果对于相同的订购键有"message1"和"message2"以及"subscriberA"和"subscriberB"来接收它们,"subscriberA"在确认之前接收了"message1",然后"subscriberB"也可能在"subscriberA"确认之前接收了"message1"。如果您需要更严格的确认截止日期保证,那么您应该在消息订购与仅一次传递功能一起使用。

"gcloud"工具不是测试关联性的好方法。关联性仅适用于使用流式拉取时,而"gcloud"不支持流式拉取。在使用gcloud时,任何拉取请求都将获取任何订购键的消息,因为每个请求没有可识别的信息来将其区分为来自特定订阅者的请求。

请注意,宣布订购键的博客文章明确说明:

关联性:如果有带有订购键的未完成消息发送到一个流式拉取订阅者,那么交付的额外消息将发送到同一个订阅者。如果当前没有为订购键未完成的消息,服务将尽力将消息交付给最后一个接收该键消息的订阅者。

官方Pub/Sub客户端库使用流式拉取,因此应该具有更可观察的关联性。

英文:

The ordering guarantee for Cloud Pub/Sub does not guarantee that an acknowledgement has to be received in order for the next message to be delivered. When using the Cloud Pub/Sub client libraries, the guarantee is that the next message for an ordering key will not be delivered to the user-specified callback until the callback completes for the previous message. If you always acknowledge your messages within the callback, then this effectively means that you are guaranteeing the next message will not be delivered until the previous is acked. However, if you acknowledge asynchronously, the next message could be delivered to your callback without the previous one having been acknowledged.

In general, these deliveries will happen to the same subscriber. It should not be possible for a different subscriber to receive a subsequent message if a previous one has not been acknowledged. However, keep in mind that Cloud Pub/Sub has at-least-once delivery semantics and ack deadlines are managed with best effort. Therefore, if you have "message1" and "message2" for the same ordering key and "subscriberA" and "subscriberB" to receive them, it is possible that "subscriberA" could receive "message1" and then "subscriberB" could also receive "message1" before "subscriberA" has acknowledged it. If you need tighter guarantees around ack deadlines, then you should use the exactly once feature in conjunction with message ordering.

The gcloud tool is not going to be a good way to test affinity. Affinity only applies when using streaming pull, which gcloud does not. When using gcloud, any pull request is going to get messages for any ordering key, as there is no identifiable information for each request to distinguish it as coming from a particular subscriber.

Note that the blog post announcing ordering keys states specifically:

> Affinity: If there are messages with an ordering key outstanding to a
> streaming pull subscriber, then additional messages that are delivered
> are sent to that same subscriber. If no messages are currently
> outstanding for an ordering key, the service delivers messages to the
> last subscriber to receive messages for that key on a best-effort
> basis.

The official Pub/Sub client libraries use streaming pull and should therefore have more observable affinity.

huangapple
  • 本文由 发表于 2023年3月7日 01:48:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75654157.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定