SQS Standard vs FIFO — в чём разница?
Standard — неограниченный TPS, at-least-once доставка, порядок не гарантирован; FIFO — строгий порядок внутри MessageGroupId, exactly-once, лимит 300 TPS (3000 с батчингом).
SQS Standard vs FIFO
Amazon SQS предлагает два типа очередей с принципиально разными гарантиями. Выбор зависит от требований к порядку сообщений и идемпотентности вашей системы.
Standard Queue
Standard — очередь с максимальной пропускной способностью и минимальными гарантиями порядка.
- Пропускная способность: неограниченная (nearly unlimited TPS).
- Доставка: at-least-once — сообщение может быть доставлено более одного раза. Потребитель обязан быть идемпотентным.
- Порядок: best-effort — порядок не гарантируется, сообщения могут прийти не в том порядке, в котором были отправлены.
- Цена: $0.40 за 1 миллион запросов.
- Подходит для: email-рассылки, генерация отчётов, обработка изображений, задачи где дублирование или перестановка допустимы.
FIFO Queue
FIFO (First-In-First-Out) обеспечивает строгий порядок и exactly-once обработку внутри группы.
- Пропускная способность: 300 TPS (без батчинга) или 3000 TPS с батчингом по 10 сообщений.
- Доставка: exactly-once — дедупликация по MessageDeduplicationId (5-минутное окно).
- Порядок: строгий внутри MessageGroupId. Разные группы обрабатываются параллельно.
- Имя очереди: обязательно оканчивается на
.fifo. - Цена: $0.50 за 1 миллион запросов.
- Подходит для: банковские транзакции, обработка заказов, машины состояний, где порядок критичен.
Создание и отправка сообщений (Python / boto3)
import boto3, uuid
sqs = boto3.client("sqs", region_name="eu-central-1")
# --- Standard Queue ---
std_url = "https://sqs.eu-central-1.amazonaws.com/123456789012/my-standard-queue"
sqs.send_message(
QueueUrl=std_url,
MessageBody='{"event": "user.registered", "user_id": 42}',
)
# --- FIFO Queue ---
fifo_url = "https://sqs.eu-central-1.amazonaws.com/123456789012/my-order-queue.fifo"
sqs.send_message(
QueueUrl=fifo_url,
MessageBody='{"event": "order.created", "order_id": 99}',
MessageGroupId="order-99", # строгий порядок внутри группы
MessageDeduplicationId=str(uuid.uuid4()), # уникальный ID для exactly-once
)
Получение и удаление сообщений
# Получить до 10 сообщений, visibility timeout 30 сек
response = sqs.receive_message(
QueueUrl=fifo_url,
MaxNumberOfMessages=10,
WaitTimeSeconds=20, # long polling
VisibilityTimeout=30,
)
for msg in response.get("Messages", []):
print(msg["Body"])
# После успешной обработки удалить
sqs.delete_message(
QueueUrl=fifo_url,
ReceiptHandle=msg["ReceiptHandle"],
)
MessageGroupId и параллелизм в FIFO
MessageGroupId — ключевой механизм масштабирования FIFO. Сообщения с одним GroupId обрабатываются строго последовательно одним потребителем за раз. Сообщения с разными GroupId обрабатываются параллельно. Для ускорения обработки распределяйте сообщения по множеству групп.
# Параллельная обработка: groupId = user_id
# Для одного пользователя — строгий порядок
# Разные пользователи — параллельно
for user_id, event in events:
sqs.send_message(
QueueUrl=fifo_url,
MessageBody=event,
MessageGroupId=f"user-{user_id}",
MessageDeduplicationId=str(uuid.uuid4()),
)
Ключевые различия в одной таблице
- Порядок: Standard — best-effort; FIFO — гарантированный внутри группы.
- Дублирование: Standard — возможно (at-least-once); FIFO — исключено в 5-мин окне (exactly-once).
- TPS: Standard — неограниченно; FIFO — 300 / 3000 с батчингом.
- Dead Letter Queue: поддерживают оба типа.
- Lambda trigger: поддерживают оба; для FIFO Lambda обрабатывает сообщения группами.
Подводные камни
- Standard at-least-once требует идемпотентности: одно и то же сообщение может прийти дважды; без защиты (idempotency key в БД) возможны двойные списания или двойные записи.
- FIFO throughput лимит жёсткий: при пиковой нагрузке 300 TPS легко исчерпать; батчинг (SendMessageBatch до 10 сообщений) увеличивает до 3000, но не безлимитно.
- MessageGroupId блокирует параллелизм: если все сообщения в одной группе, обработка будет строго последовательной — один consumer за раз, независимо от числа воркеров.
- Окно дедупликации 5 минут: повторный MessageDeduplicationId блокирует доставку на 5 минут; после истечения то же значение снова будет принято.
- Visibility timeout: если обработка занимает больше времени, чем visibility timeout, сообщение станет снова видимым и будет доставлено повторно — нужно вызывать ChangeMessageVisibility.
- Нельзя конвертировать тип очереди: Standard нельзя превратить в FIFO и наоборот — нужно создавать новую очередь и мигрировать.
- Long polling обязателен: без WaitTimeSeconds=20 возникают пустые получения, которые тоже тарифицируются и увеличивают стоимость.
Common mistakes
- Не делать Standard consumer idempotent.
- Считать FIFO глобально последовательной без group design.
- Создавать один message group для всего high-throughput workload.
What the interviewer is testing
- Различает at-least-once и FIFO ordering.
- Понимает message group ID и deduplication.
- Учитывает throughput/concurrency trade-offs.