网络请求会失败。请求超时、Pod 在发送过程中重启、重试库触发了两次——任何一种情况都可能在邮件 API 没有防护的情况下导致重复发送。幂等键是在 API 层解决这个问题的标准方法。
没有幂等性会发生什么
您调用 POST /emails,请求到达服务器,服务器发出邮件,然后在收到 200 响应之前连接断开。您的代码看到超时后重试。没有幂等性,服务器会将第二次调用视为新请求并再次发送邮件。收件人会收到两封密码重置邮件、两份发票或两封确认邮件——这是一个很难事后排查的真实客服问题。
幂等键的工作原理
您为每次逻辑发送生成一个唯一键——通常是 UUID——并将其包含在请求头中。服务器在处理请求时记录该键。如果相同的键在去重窗口内(Rovela 为 24 小时)再次出现,服务器会返回原始响应而不执行任何操作。从调用方角度看,请求成功了;但没有发送重复邮件。
如何生成正确的键
键必须对每次逻辑发送唯一,而不是对每次 HTTP 请求唯一。在任何重试循环之前生成一次,并对该逻辑操作的每次尝试使用相同的值。一个常见错误是在每次重试时生成新的 UUID——这完全失去了幂等性的意义。建议将键与实体绑定:对于订单确认,订单 ID 加事件类型的哈希值效果很好;对于一次性消息,在发送流程开始时生成一次随机 UUID 即可。
Rovela 对重复请求的返回结果
当 Rovela 收到一个已处理过键的请求时,会返回 HTTP 200 及原始响应体,包括原始消息 ID。您的代码看到成功响应,可以安全地记录消息 ID。收件人只收到了一封邮件。Rovela 的去重窗口为 24 小时;超过此时间的键会过期,新的发送请求会正常处理。
何时不需要键
只有在您明确希望允许重复时才省略键——例如,用户点击重发按钮应该生成新键,这样邮件才会真正再次发出。大多数事务性发送都应该包含键。批量营销邮件通常不需要幂等性,因为它们的重试方式与事务性调用不同。
常见问题
- 幂等键和消息 ID 是一回事吗?
- 不是。消息 ID 由 Rovela 在邮件被接受后分配,用于在日志和 Webhook 中标识该邮件。幂等键由调用方在发送前提供,用于标识逻辑发送操作以进行去重。您提供键;Rovela 返回 ID。
- 键的格式应该是什么?
- 任何不超过 256 个字符的字符串都可以。UUID v4 是惯常选择,因为它的碰撞概率极低,在各类运行时中都有现成支持。不要使用会在不同发送之间重复的值,例如单独使用收件人地址或时间戳。
- 键在不同 API Key 之间有效吗?
- 是的,在同一组织内有效。Rovela 的去重以组织为作用域,而非单个 API Key。同一组织下的不同 API Key 共享同一去重空间——无论哪个 Key 发出了请求,相同的幂等键都能阻止重复发送。不同组织的键互相独立。
- 如果键意外碰撞会发生什么?
- Rovela 会返回原始响应而不是发送新邮件。如果您不小心对一次真正不同的发送重用了键,第二次发送会被静默去重。请使用足够熵的键生成方式——UUID v4 有 122 位随机性,实际上不可能发生意外碰撞。