#message-queue #distributed-computing #amazon-sqs #producer-consumer
#очередь сообщений #распределенные вычисления #amazon-sqs #производитель-потребитель
Вопрос:
У меня есть очередь (в данном случае Amazon SQS), и есть N запущенных узлов одной и той же службы, которые получают сообщения от SQS.
Как я могу убедиться, что в любой момент времени не более одного узла прочитали одно и то же сообщение из очереди.
В случае Kafka мы знаем, что к одному тематическому разделу может быть отнесено не более одного пользователя из одной и той же группы пользователей. Как мы можем убедиться, что внутри Amazon SQS обрабатывается одно и то же или нет?
Ответ №1:
Механизм Amazon, предотвращающий доставку сообщения нескольким потребителям, — это тайм-аут видимости:
Сразу после получения сообщения оно остается в очереди. Чтобы другие пользователи не могли повторно обработать сообщение, Amazon SQS устанавливает тайм-аут видимости, период времени, в течение которого Amazon SQS запрещает другим пользователям получать и обрабатывать сообщение. Время ожидания видимости сообщения по умолчанию составляет 30 секунд. Минимум — 0 секунд. Максимум — 12 часов.
После получения сообщения SQS запускает тайм-аут и в течение всего этого времени не отправляет его повторно другим потребителям. По истечении времени ожидания, если сообщение не было удалено, SQS снова делает его доступным для других потребителей.
Но, как говорится в примечании:
Для стандартных очередей время ожидания видимости не является гарантией от получения сообщения дважды. Дополнительные сведения см. в разделе Доставка по крайней мере один раз.
Если вам нужны абсолютные гарантии доставки только один раз, вы должны выбрать:
- Разработайте свое приложение как идемпотентное, чтобы результат был одинаковым, если оно обрабатывает одно и то же сообщение один или более раз.
- Попробуйте использовать очередь FIFO SQS, которая обеспечивает обработку ровно один раз.
Комментарии:
1. Конечно, возникнет необходимость сделать нашу систему идемпотентной (чтобы избежать многократной обработки одного и того же сообщения на разных узлах) и, следовательно, создать единую точку ресурса (db) и поддерживать статус, который будет общим для всех узлов, но это в конечном итоге приведет к увеличению нагрузки на систему в случае огромного количества сообщений, обрабатываемых в единицу времени. Я не хочу, чтобы моя система была устроена таким образом, чтобы она каждый раз искала db, прежде чем начать обработку сообщения.
2. Кроме того, я понимаю концепцию времени видимости, но в конце SQS будет обработано, что одно и то же сообщение не будет готово к обработке. Я как бы ищу причину, по которой это позволяет избежать одновременного поиска сообщения более чем одним потребителем.
3. Я не уверен, что полностью понимаю, что вы имеете в виду этим предложением: «Я как бы ищу причину, по которой это позволяет избежать одновременного поиска сообщения несколькими потребителями». В любом случае я бы не стал сильно беспокоиться о чрезмерной загрузке: при правильно установленном тайм-ауте видимости маловероятно, что SQS доставит сообщение более одного раза. И если проверка базы данных может вызвать некоторую нагрузку на вашу систему, возможно, вы можете использовать какой-нибудь другой быстрый ресурс в качестве источника достоверности для проверки того, было ли сообщение уже обработано, например Redis.
4. SQS не доставит сообщение более одного раза, но возможно ли, что одно и то же сообщение обрабатывается двумя экземплярами одного и того же сервиса. Я хочу понять, что происходит, когда потребитель прослушивает очередь, создает ли он сеанс при получении сообщения или что-то еще, чтобы убедиться, что «никакие два экземпляра одной и той же службы не начинают работать с одним и тем же сообщением». Я надеюсь, это поможет вам понять, о чем именно я думаю.
5. Это зависит от вашего приложения. Реализация сервисов (потребителей) полностью зависит от вас. Ответственность SQS заключается только в доставке сообщения. Что происходит потом — это ваш выбор (как разработчика / системного дизайнера).