Ответ 1
Как упоминалось в других ответах, вы не можете предотвратить дублирование сообщений, поступающих из SQS.
В большинстве случаев ваши сообщения будут переданы одному из ваших потребителей один раз, но вы будете запускать дубликаты на определенном этапе.
Я не думаю, что есть простой ответ на этот вопрос, потому что он влечет за собой создание правильной архитектуры, которая может справиться с дубликатами, что означает ее идемпотентность в природе.
Если все рабочие в вашей распределенной архитектуре были идемпотентны, это было бы легко, потому что вам не нужно было бы беспокоиться о дубликатах. Но на самом деле такого рода среда не существует, где-то по пути что-то не сможет справиться с ней.
В настоящее время я работаю над проектом, где мне требуется решить эту проблему, и придумать подход к ее решению. Я думал, что это может принести пользу другим, чтобы поделиться своим мнением здесь. И это может быть хорошим местом, чтобы получить некоторые отзывы о моем мышлении.
Хранилище факсов
Это очень хорошая идея для развития сервисов, чтобы они собирали факты, которые теоретически могут воспроизводиться, чтобы воспроизвести одно и то же состояние во всех затронутых нижележащих системах.
Например, скажем, вы строите брокер сообщений для платформы торговли акциями. (Я на самом деле работал над таким проектом раньше, это было ужасно, но и хороший опыт обучения.)
Теперь скажем, что эта сделка приходит, и в ней заинтересованы 3 системы:
- Старый мэйнфрейм школы, который должен оставаться обновленным.
- Система, которая объединяет все сделки и делится ею с партнерами на FTP-сервере.
- Служба, которая регистрирует сделку и перераспределяет акции новому владельцу
Это немного запутанно, я знаю, но идея состоит в том, что одно сообщение (факт), входящее в него, имеет различные распределенные последующие эффекты.
Теперь представьте, что мы поддерживаем магазин фактов, запись всех сделок, поступающих в наш брокер. И что все 3 провайдера обслуживания вниз по течению звонят нам, чтобы сообщить нам, что они потеряли все свои данные за последние 3 дня. Загрузка FTP на 3 дня позади, мейнфрейм на 3 дня позади, и все сделки отстают на 3 дня.
Поскольку у нас есть магазин фактов, мы могли бы теоретически воспроизвести все эти сообщения с определенного времени до определенного времени. В нашем примере это будет с 3 дней назад до сих пор. И нисходящие сервисы могут быть догнаны.
Этот пример может показаться немного верхним, но я пытаюсь передать что-то очень конкретное: факты - важные вещи, которые нужно отслеживать, потому что это то, что мы будем использовать в нашей архитектуре для сражения с дубликатами.
Как хранилище фактов помогает нам с повторяющимися сообщениями
При условии, что вы реализуете свой магазин фактов на уровне сохранения, который дает вам части CA теорему CAP, согласованность и доступность, вы можете сделать следующее:
Как только сообщение будет получено из очереди, вы проверите свой магазин фактов, видели ли вы это сообщение раньше, и если у вас есть, заблокирован ли он в данный момент и находится в состоянии ожидания. В моем случае я буду использовать MongoDB для реализации своего магазина фактов, так как мне это очень нравится, но различные другие технологии БД должны иметь возможность справиться с этим.
Если этот факт еще не существует, он будет вставлен в хранилище фактов с ожидающим состоянием и временем истечения срока блокировки. Это должно быть сделано с использованием атомных операций, потому что вы не хотите, чтобы это произошло дважды! Здесь вы гарантируете свою услугу idempotence.
Счастливый случай - чаще всего происходит
Когда Fact Store вернется к вашей службе, сообщив, что этого факта не существует, и что была создана блокировка, служба пытается это сделать. После этого он удалит сообщение SQS и отметит завершенный факт.
Дублирующее сообщение
Итак, что происходит, когда приходит сообщение, а это не дубликат. Но давайте посмотрим, когда приходит дублирующее сообщение. Служба подбирает его и просит магазин фактов записать его с помощью блокировки. Хранилище фактов сообщает, что оно уже существует и что оно заблокировано. Служба игнорирует сообщение и пропускает его! Как только обработка сообщений будет выполнена другим рабочим, он удалит это сообщение из очереди, и мы больше не увидим его.
Случай с бедствиями - редко бывает
Итак, что происходит, когда служба впервые регистрирует этот факт в магазине, затем получает блокировку на определенный период, но падает? Хорошо SQS снова представит вам сообщение, если оно было подобрано, но не удалено в течение определенного периода после его подачи из очереди. Вот почему мы кодируем наш магазин фактов таким образом, чтобы служба поддерживала блокировку в течение ограниченного времени. Поскольку, если он падает, мы хотим, чтобы SQS представила сообщение службе или другой экземпляр этого позднее, позволяя этой службе предположить, что этот факт должен быть включен в состояние (выполнено) еще раз.