

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Amazon SQS 消息重复数据删除和分组
<a name="best-practices-message-deduplication"></a>

本主题提供了可确保在 Amazon SQS 中实现一致消息处理的最佳实践，并说明了如何使用：
+ [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html#API_SendMessage_RequestSyntax](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html#API_SendMessage_RequestSyntax) 防止 FIFO 队列中出现重复消息。
+ [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) 管理不同消息组内的消息排序。

****主题****
+ [避免 Amazon SQS 中出现不一致的消息处理](avoiding-inconsistent-message-processing.md)
+ [使用消息重复数据删除 ID](using-messagededuplicationid-property.md)
+ [使用消息组 ID](using-messagegroupid-property.md)
+ [使用接收请求尝试 ID](using-receiverequestattemptid-request-parameter.md)

# 避免 Amazon SQS 中出现不一致的消息处理
<a name="avoiding-inconsistent-message-processing"></a>

由于 Amazon SQS 是一个分布式系统，因此，即使在从 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html) API 方法调用成功返回时 Amazon SQS 将消息标记为已发送，使用者也可能不会收到消息。在这种情况下，Amazon SQS 将消息记录为至少已发送一次，即使使用者从未收到过也是如此。由于在这些情况下不会再尝试发送消息，因此我们不建议将[死信队列](sqs-dead-letter-queues.md)的最大接收数量设置为 1。

# 在 Amazon SQS 中使用消息重复数据删除 ID
<a name="using-messagededuplicationid-property"></a>

[https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) 是一种令牌，仅用于防止在 Amazon SQS FIFO 队列中重复传递消息。它可以确保在 5 分钟的重复数据删除时段内，仅处理和传送具有相同重复数据删除 ID 的消息的一个实例。

如果 Amazon SQS 已接受具有特定重复数据删除 ID 的消息，则任何具有相同 ID 的后续消息都将被确认，但不会传送给使用者。

**注意**  
即使消息已被接收并删除，Amazon SQS 仍会继续跟踪重复数据删除 ID。

**Topics**
+ [在 Amazon SQS 中提供消息重复数据删除 ID](providing-message-deduplication-id.md)
+ [在 Amazon SQS 为单个创建者/使用者系统启用重复数据删除](single-producer-single-consumer.md)
+ [Amazon SQS 中的中断恢复场景](designing-for-outage-recovery-scenarios.md)
+ [在 Amazon SQS 中配置可见性超时](working-with-visibility-timeouts.md)

# 在 Amazon SQS 中提供消息重复数据删除 ID
<a name="providing-message-deduplication-id"></a>

创建者应在以下场景中指定消息重复数据删除 ID：
+ 发送相同消息正文但必须将其视为唯一项时。
+ 发送内容相同但消息属性不同的消息时，确保对每条消息进行独立处理。
+ 发送内容不同（例如消息正文包含重试计数器）但要求 Amazon SQS 将其识别为重复项的消息时。

# 在 Amazon SQS 为单个创建者/使用者系统启用重复数据删除
<a name="single-producer-single-consumer"></a>

如果您有单一的创建者和单一的使用者，且消息因包含特定于应用程序的消息 ID 而具有唯一性，请遵循以下最佳实践：
+ 为队列启用基于内容的重复数据删除（每条消息都具有唯一的正文）。创建者可忽略消息重复数据删除 ID。
+ 如果您为 Amazon SQS FIFO 队列启用了基于内容的重复数据删除，并且发送了具有重复数据删除 ID 的消息，则 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) 重复数据删除 ID 将覆盖生成的基于内容的重复数据删除 ID。
+ 尽管使用者无需为每个请求提供接收请求尝试 ID，但最好提供，因为这样可以更快地执行失败-重试序列。
+ 请求不会干扰消息在 FIFO 队列中的顺序，因此可重试发送或接收请求。

# Amazon SQS 中的中断恢复场景
<a name="designing-for-outage-recovery-scenarios"></a>

FIFO 队列中的重复数据删除过程具有时效性。在设计应用程序时，请确保创建者和使用者均可在客户端或网络中断时恢复运行，而不会引入重复数据或出现处理失败。

创建者注意事项
+ Amazon SQS 强制执行 5 分钟的重复数据删除时段。
+ 如果创建者在 5 分钟后重试 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) 请求，Amazon SQS 会将其视为新消息，这可能导致消息重复。

使用者注意事项
+ 如果使用者未能在可见性超时结束前处理消息，其他使用者可能会接收并处理该消息，从而导致重复处理。
+ 根据应用程序的处理时间调整可见性超时。
+ 使用 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ChangeMessageVisibility.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ChangeMessageVisibility.html) API 在消息仍在处理时延长超时。
+ 如果消息反复处理失败，请将其路由至[死信队列（DLQ）](sqs-dead-letter-queues.md)，而不是允许无限期地对其进行重新处理。
+ 创建者必须了解队列的重复数据删除间隔。Amazon SQS 的重复数据删除间隔为 5 分钟。在重复数据删除时间间隔过期后重试 `SendMessage` 请求可能会将重复的消息引入队列中。例如，车辆中的移动设备将发送其顺序很重要的消息。如果车辆在接收确认前一段时间失去手机网络连接，则在重新获得手机网络连接之前重试请求可能产生重复项。
+ 使用者必须具有可见性超时，以便将在可见性超时过期之前无法处理消息的风险降至最低。您可通过调用 `ChangeMessageVisibility` 操作延长处理消息时的可见性超时。但是，如果可见性超时过期，其他使用者可立即开始处理消息，从而导致多次处理消息。要避免这种情况，请配置[死信队列](sqs-dead-letter-queues.md)。

# 在 Amazon SQS 中配置可见性超时
<a name="working-with-visibility-timeouts"></a>

为确保可靠的消息处理，请将可见性超时设置为比 AWS SDK 读取超时长。这一设置适用于使用 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html) API 进行短轮询和长轮询的情况。较长的可见性超时可防止消息在原始请求完成之前提供给其他使用者，从而降低重复处理的风险。

# 结合使用消息组 ID 和 Amazon SQS FIFO 队列
<a name="using-messagegroupid-property"></a>

在 FIFO（先进先出）队列中，[https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) 是一个将消息组织成不同组的属性。同一消息组内的消息始终按照严格的顺序逐条处理，从而确保同一组内绝不会有两条消息同时被处理。在标准队列中，使用 `MessageGroupId` 启用[公平队列](sqs-fair-queues.md)。如果需要严格排序，请使用 FIFO 队列。

**Topics**
+ [在 Amazon SQS 中交错多个有序消息组](interleaving-multiple-ordered-message-groups.md)
+ [在 Amazon SQS 的多创建者/使用者系统中避免处理重复消息](avoding-processing-duplicates-in-multiple-producer-consumer-system.md)
+ [避免在 Amazon SQS 中出现具有相同消息组 ID 的大量消息积压](avoid-backlog-with-the-same-message-group-id.md)
+ [避免在 Amazon SQS 中的虚拟队列中重复使用相同的消息组 ID](avoiding-reusing-message-group-id-with-virtual-queues.md)

# 在 Amazon SQS 中交错多个有序消息组
<a name="interleaving-multiple-ordered-message-groups"></a>

要在交错一个 FIFO 队列中的多个有序消息组，请为每个组分配一个 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)（例如，不同用户的会话数据）。这可以让多个使用者能够同时从队列中读取消息，同时确保同一组内的消息按顺序处理。

当具有特定 `MessageGroupId` 的消息正在进行处理且不可见时，任何其他使用者均无法处理来自同一组的消息，直至可见性超时结束或消息被删除。

# 在 Amazon SQS 的多创建者/使用者系统中避免处理重复消息
<a name="avoding-processing-duplicates-in-multiple-producer-consumer-system"></a>

在一个高吞吐量、低延迟且消息顺序并非优先事项的系统中，创建者可为每条消息分配唯一的 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)。这可以确保即使在多创建者/多使用者设置中，Amazon SQS FIFO 队列也能消除重复项。虽然这种方法可以防止重复的消息，但无法保证消息的顺序，因为每条消息都被视为自己的独立组。

在任何具有多个创建者和使用者的系统中，都存在重复传递消息的风险。如果使用者未能在可见性超时结束前处理消息，Amazon SQS 会使该消息再次可用，从而导致其他使用者可能会接收该消息。为了缓解这个问题，请确保根据处理时间正确设置消息确认和可见性超时。

# 避免在 Amazon SQS 中出现具有相同消息组 ID 的大量消息积压
<a name="avoid-backlog-with-the-same-message-group-id"></a>

FIFO 队列最多支持 12 万条传输中消息（使用者已接收但尚未删除的消息）。如果达到此上限，Amazon SQS 不会返回错误，但处理可能会受到影响。您可以联系 [AWS Support](https://docs.aws.amazon.com/awssupport/latest/user/create-service-quota-increase.html) 申请提高此上限。

FIFO 队列会浏览前 12 万条消息，以确定可用的消息组。如果单个消息组中积压了大量消息，则在积压消息处理完毕之前，其他组后续发送的消息将持续被阻止。

**注意**  
当使用者反复多次处理失败时，就可能会导致消息积压。这可能是由于消息内容问题或使用者端故障所致。为防止消息处理延迟，请配置[死信队列](sqs-dead-letter-queues.md)，用于在多次处理失败后转移未处理的消息。这样可以确保同一消息组中的其他消息得到处理，从而避免系统出现瓶颈。

# 避免在 Amazon SQS 中的虚拟队列中重复使用相同的消息组 ID
<a name="avoiding-reusing-message-group-id-with-virtual-queues"></a>

将虚拟队列与共享主机队列一起使用时，请避免在不同的虚拟队列中重复使用相同的 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)。如果多个虚拟队列共享同一主机队列且包含具有相同 `MessageGroupId` 的消息，这些消息可能会相互阻塞，以至阻碍高效处理。为确保顺利处理消息，请为不同虚拟队列中的消息分配唯一的 `MessageGroupId` 值。

# 使用 Amazon SQS 接收请求尝试 ID
<a name="using-receiverequestattemptid-request-parameter"></a>

接收请求尝试 ID 是 Amazon SQS 中用于删除 [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html) 重复调用的唯一令牌。当您的应用程序与 Amazon SQS 之间出现网络中断或连接问题时，最佳实践是：
+ 在调用 `ReceiveMessage` 时提供接收请求尝试 ID。
+ 如果操作失败，请使用相同的接收请求尝试 ID 重试。