Delivery Guarantees Explained | Exactly-Once vs At-Least-Once vs At-Most-Once
Tejav Academy · 2026-05-30 · 8м 30с · 20 просмотров · YouTube ↗
Топики: durable-execution
🎧 Аудио
📝 Summary
model=deepseek-v4-flash · prompt=summary-v7 · 3 704→1 842 tokens · 2026-07-20 15:09:37
🎯 Главная суть
В распределённых системах невозможно полностью гарантировать, что сообщение будет обработано ровно один раз из-за неотъемлемой ненадёжности сети. Инженеры выбирают между двухблочной доставкой (at-least-once) — с обязательной обработкой хотя бы один раз, но с возможными дубликатами — и строгой доставкой (exactly-once), которая требует сложного управления состоянием. На практике предпочитают at-least-once в сочетании с идемпотентностью потребителей, что даёт высокую масштабируемость и приемлемую корректность.
Проблема дублирования: катастрофа с оплатой
В системах, где микросервисы обмениваются событиями, типичный сценарий сбоя выглядит так: потребитель успешно получает и обрабатывает сообщение (например, списывает 10 000 рублей), обновляет базу данных, но перед отправкой подтверждения (ACK) обратно в брокер (Kafka) у него происходит сбой. Брокер, не получив ACK, считает, что сообщение не обработано, и пересылает его другому потребителю. В результате клиент платит дважды. Аналогичная ситуация в сервисе доставки еды: один заказ порождает три одинаковые пиццы у двери. Именно этот страх дубликатов заставляет инженеров искать надёжные гарантии доставки.
Exactly-once: идеал, которого сложно достичь
Exactly-once означает, что сообщение обрабатывается строго один раз, без потерь и дубликатов. Это абсолютно необходимо для банковских переводов, инвентаризации и любых операций, где дублирование недопустимо. Однако распределённые сети по своей природе враждебны: брокеры падают, разрывы сети изолируют серверы, подтверждения теряются. Чтобы поддерживать согласованное состояние в такой среде, нужно отслеживать идентификаторы сообщений, транзакции и синхронизировать состояние между машинами. Это требует огромных накладных расходов и сильно ограничивает масштабируемость.
At-least-once: прагматичный выбор
Из-за сложности exactly-once индустрия в основном полагается at-least-once. Эта гарантия обещает, что сообщение будет доставлено один или более раз — дубликаты допускаются, но ни одно сообщение никогда не теряется. Фундаментальный принцип: «лучше дубликат, чем потеря данных». Потеря платежа (клиент заплатил, но услуга не оказана) гораздо хуже, чем повторная обработка, которую можно обнаружить и исправить.
Компромисс: корректность против производительности
Exactly-once даёт сильную корректность ценой дорогого управления состоянием, что снижает пропускную способность. At-least-once обеспечивает простую архитектуру, высокую масштабируемость (миллионы событий в секунду), но перекладывает проблему дубликатов на прикладной уровень. Выбор зависит от сценария: банковские системы требуют exactly-once; высоконагруженные системы логирования, аналитики кликов или push-уведомлений могут использовать at-least-once — дублирующее уведомление лишь раздражает пользователя, но не ведёт к катастрофе.
Идемпотентность: решение дубликатов
Идемпотентный потребитель — это обработчик, который при многократном получении одного и того же события даёт одинаковый результат (например, не списывает деньги повторно). Типовая реализация использует таблицу дублирования (deduplication table) в базе данных:
- Получить сообщение с уникальным ID.
- Проверить, существует ли ID в таблице.
- Если существует — проигнорировать сообщение и отправить успешный ACK брокеру.
- Если новый — выполнить бизнес-логику и записать ID, чтобы в будущем не обрабатывать повторно. Такой подход позволяет сочетать масштабируемость at-least-once с защитой от дубликатов.
Инструменты и паттерны для надёжности
Современные брокеры, такие как Apache Kafka, предоставляют встроенную поддержку exactly-once семантики: идемпотентные продюсеры присваивают сообщениям порядковые номера, а транзакционные потребители связывают управление смещениями (offsets) с фиксацией изменений в базе данных. В облачных микросервисах Kafka часто комбинируют с паттернами inbox/outbox, где каждое событие сначала сохраняется в «почтовом ящике», а затем отправляется только после атомарного обновления состояния.
Практические рекомендации для инженеров и собеседований
На собеседованиях по проектированию систем важно демонстрировать зрелость: проектировать идемпотентные потребители, использовать уникальные ID для дедупликации, добавлять мониторинг повторных попыток (retry storms) и настраивать dead‑letter queues (DLQ) для сообщений, которые не удаётся обработать. Ключевое отличие начинающего инженера от опытного — первый предполагает, что сеть надёжна, а второй исходит из того, что сбои неизбежны, и строит защитные механизмы. Лучший компромисс для крупных систем (Amazon, Netflix) — at-least-once с жёстко протестированной идемпотентностью.
📜 Transcript
en · 1 395 слов · 21 сегментов · clean
Показать текст транскрипта
Welcome to This Explainer. Today we're diving into one of the absolute most stress-inducing, keep-you-up-at-night reliability problems in distributed systems, message delivery guarantees. Honestly, if you get this wrong, you're looking at absolute chaos in production. To really wrap our heads around why this matters so much, just imagine this scenario for a second. A customer is on your platform, right? And they click to pay 10,000 rupees for a service. The network request goes out, but suddenly it just times out. So your application, trying to be helpful, automatically retries the transaction. And then the absolute worst-case scenario strikes. The customer gets charged twice. Or think about a food delivery app where a single hungry customer suddenly has three identical pizzas showing up at their front door. It's a nightmare. This kind of catastrophic failure brings us to a massive, massive engineering question. Can distributed systems actually guarantee exactly once delivery? Like, can we build a system that flawlessly processes a message one time and only one time, no matter how many network crashes, timeouts, or server failures we throw at it? Section 1. The Duplicate Payment Disaster Top engineering teams, we're talking companies like Uber, Stripe, Netflix, they obsess over this stuff. They know that in an event-driven system, microservices are constantly talking to each other, and messages can so easily get lost or duplicated. So here's the famous distributed systems trap mapped out. Step 1. Your consumer successfully receives and processes a payment event. Great. Step 2. It securely updates the database, actually deducting the funds. But then, in step 3, disaster strikes. The consumer literally crashes right before sending the acknowledgement back to Kafka. Because the message broker never got that ACK, it just assumes the message failed. So in step 4, the broker resends the exact same event to another consumer. Did the payment actually happen the first time? Yes. Does the system know that? No. Boom! Double charge. Section 2. Exactly one's delivery explained. To prevent this kind of absolute chaos, engineers naturally look to the holy grail of reliability first. exactly once delivery. This guarantees that a message is processed exactly one time. No duplicates are created and absolutely no messages are dropped or lost. It literally doesn't matter if your servers restart or if your network completely drops for 10 seconds, the system handles it perfectly. And honestly, this is an absolute necessity if you're safely transferring, say, 1000 rupees between bank accounts. But here's the catch, and this brilliantly illustrates why guaranteeing true exactly one semantics is incredibly difficult. Distributed networks are just inherently messy, right? They're hostile. You're dealing with sudden broker crashes, severe network partitions where servers literally can't even talk to each other, consumers randomly restarting, and those totally lost acknowledgments we just talked about. Trying to maintain perfect, coordinated state across multiple isolated machines during a massive retry storm, it requires incredibly heavy, complex engineering. Section 3. At least once delivery. Explained. Because of all those immense difficulties, and honestly the massive overhead required to perfectly track state, the industry heavily relies on a totally different approach. At least once delivery. This guarantees that a message is delivered one or more times. It strictly accepts that, hey, duplicate deliveries will happen when acknowledgement responses fail or networks hiccup. But the core promise here? A message is never, ever lost. And that brings us to a fundamental mantra in backend engineering. Better duplicate than data loss. Distributed systems overwhelmingly prefer this model. Why? Because losing a payment event entirely, meaning a user paid but literally never got their service, or a transaction just vanished into thin air, is far, far worse than processing a duplicate that we could potentially catch and fix later on. Section 4. The Core Engineering Trade-off So what's really interesting here is how these two philosophies fundamentally clash in real production environments. We've got a massive trade-off on our hands. On one side, exactly once gives you strong correctness, but it requires really expensive, complex state management. You have to meticulously track message IDs and transaction boundaries, which naturally drags down your system's overall scalability. On the other side, At Least Once offers a much simpler architecture. It's highly scalable, it can process millions of events effortlessly, but it forces your application layer to deal with the messy reality of duplicate processing. This breaks down exactly where each approach shines. You absolutely must use Exactly Once architectures when a duplicate is just unacceptable. Think banking systems, financial ledgers, or inventory accounting. But you should absolutely use at least once for high-throughput use cases, things like logging systems, clickstream analytics pipelines, or sending push notifications. I mean, if a user gets the same marketing notification twice, it's slightly annoying, sure, but it's totally manageable compared to crashing your entire database trying to prevent it. Section 5. Fixing duplicates with item potency So if we're using at least once for its massive scalability, How do we actually prevent that duplicate payment disaster we started with? Well, the crucial answer is building idempotent consumers. In software engineering, idempotency simply means a consumer safely handles retries by producing the exact same result no matter how many times it processes the same event. So if that food delivery app receives the same order placed event two, three, or even ten times, an idempotent system won't charge the customer again, and it certainly won't assign multiple drivers to pick up a single pizza. We typically achieve this using what's called a duplication table right inside our database. Here's how the flow actually works. First, you receive a message that has a unique, universally recognized ID. Second, before you execute any business logic, you check your duplication table. If that ID already exists, step three tells you to safely ignore the duplicate and just send a success acknowledgement back to the broker. It's just a harmless duplicate, right? Only if it's a new ID do you move to step four, process the payment, and securely store that ID so you never, ever process it again. Now, it's also worth noting that modern infrastructure tools have evolved to help us out with this. Technologies like Apache Kafka now offer advanced exactly-once semantics built right in. They use awesome features like item potent producers that tag messages with sequence numbers and transactional consumers that bind offset management with database commits. When you're building cloud-native microservices, you'll actually often see these Kafka features combined with advanced architectural designs like the inbox and outbox patterns to guarantee absolute reliability. Section 6. System Design Interview Mastery Let's see how all of this builds into the ultimate cheat sheet for your next back-end engineering or system design interview. Interviewers absolutely love testing candidates on delivery guarantees because they want to see real production engineering maturity. They want to know your code will actually survive in the real world, so always emphasize these best practices. Proudly state that you design item-potent consumers and rely on unique IDs for deduplication. Talk about adding observability to monitor for those dangerous retry storms, and definitely mention routing toxic, unprocessable messages into dead letter queues or DOQs so they don't block your entire event pipeline. And above all, always express a preference for architectural simplicity over needless complexity. This perfectly highlights the difference in mindsets, honestly. A beginner assumes networks are perfectly reliable. They'll write a piece of code, test it once locally, assume Kafka just magically solves every problem, and completely ignore retry handling. A senior engineer, however, they architect their systems with the absolute terrifying certainty that duplicates, network crashes, and server failures will happen, and they build the safety nets to catch them. Ultimately, the most elegant and scalable solution chosen by top tech giants, from Amazon to Netflix, is almost always at least one's delivery, paired with strict, heavily tested item potency. It literally gives you the speed and resilience of a highly distributed system without sacrificing the correctness your users demand. So I leave you with this final, provocative question. How will your architecture survive its next retry storm? Have you built the right item potency to protect your users? Think about it. And hey, if this explainer helped you master this massive engineering challenge, hit that like button, subscribe for more explainers, and keep learning. See you in the next one.
⚙️ Pipeline jobs
| Stage | Status | Att. | Updated | Error |
|---|---|---|---|---|
| download | done | 1/3 | 2026-07-20 15:08:46 | |
| transcribe | done | 1/3 | 2026-07-20 15:09:17 | |
| summarize | done | 1/3 | 2026-07-20 15:09:37 | |
| embed | done | 1/3 | 2026-07-20 15:09:39 |
📄 Описание YouTube
Показать
🚀 How do distributed systems ensure messages are delivered correctly? When services communicate through Kafka, RabbitMQ, AWS SQS, or other message brokers, engineers must choose the right delivery guarantee. But here's the challenge: Do you prioritize speed, reliability, or avoiding duplicates? In this video, you'll learn: ✅ What Delivery Guarantees Are ✅ At-Most-Once Delivery Explained ✅ At-Least-Once Delivery Explained ✅ Exactly-Once Delivery Explained ✅ Duplicate Message Challenges ✅ Reliability vs Performance Trade-offs ✅ Kafka Delivery Guarantees ✅ Idempotency and Deduplication ✅ Real-World Microservices Examples ✅ System Design Interview Questions Perfect for: Software Engineers Backend Developers Distributed Systems Engineers Kafka Engineers Senior Software Engineers System Design Interview Preparation By the end of this video, you'll understand when to use each delivery guarantee and how modern event-driven systems achieve reliable communication at scale. 📌 Part of the Production-Ready Software Engineering Series. #DeliveryGuarantees #DistributedSystems #Kafka #Microservices #SystemDesign #SoftwareEngineering #EventDrivenArchitecture #BackendEngineering #TechInterviews #ProductionSystems