具有副作用的幂等性

Idempotency with side effects

假设我有一个消息队列,我在其中放置消息说我想向用户发送电子邮件。

如果我使用的消息代理提供“至少一次”传递保证,那么从我阅读的所有资源中,他们会说“你必须确保你的处理是幂等的”。

但是,对于像发送电子邮件这样的副作用,我不明白这是怎么可能的。

我有两个可能的选择:

收到消息后,我会检查数据库以查看消息 ID 是否存在。如果是这样,我会跳过该消息作为重复。

然而,第一种情况给我留下了“至多一次”发送电子邮件的语义(如果发送电子邮件失败,下次看到消息时将跳过),第二种情况给我“at至少一次”语义(如果将 ID 存储在数据库中失败,我将最终发送多封电子邮件)。

我读过的一些内容说“你需要一封支持幂等性的电子邮件 API”,但据我所知,这只会将问题推到他们的服务器上——他们仍然面临同样的困境。

我是不是漏掉了什么?还是当处理具有外部副作用时就不可能进行幂等消息处理?

我要声明电子邮件本身不支持 exactly-once 语义。当使用 SMTP 协议时,您的一方总是会在远端确认和您坚持确认之间崩溃。最好的办法是使用 at-least once 语义。

但您可能会获得 exactly-once 用户体验体验。如果您每次 send/resend 一条消息都使用相同的消息 ID,那么客户端(邮件客户端)可能会删除这些消息的重复项。有关详细信息,请参阅 https://en.wikipedia.org/wiki/Message-ID