Дублі замовлень під час роботи з API: причини та захист
Чому дублі з'являються після однієї дії
Власник панелі може натиснути кнопку один раз і побачити кілька однакових замовлень: на підписників, перегляди, реакції або іншу послугу. Зазвичай проблема не в самому кліку, а в ланцюжку між клієнтом, API, базою даних і постачальником.
З погляду сервера «один запит» не завжди один. Клієнт міг не отримати відповідь, повторити відправлення, а перша операція вже встигла зберегтися. Іноді замовлення створюється один раз у базі панелі, але двічі йде постачальнику. Це різні сценарії, і виправляються вони по-різному.
Таймаут не означає, що замовлення не створено
Найчастіша причина — клієнт чекає на відповідь обмежений час. Сервер приймає запит, створює замовлення, але відповідає пізніше за встановлений таймаут. Клієнт вважає операцію неуспішною і надсилає її повторно.
У результаті перше замовлення вже є в базі, а другий запит створює ще одне. Особливо часто це трапляється при повільній відповіді зовнішнього API, перевантаженій черзі або нестабільному з'єднанні між сервісами.
Таймаут говорить лише про відсутність відповіді, а не про відсутність обробки запиту.
Автоматичні повтори на боці клієнта
Бібліотеки для HTTP-запитів, фонові задачі та інтеграційні сервіси нерідко повторюють запит автоматично. Приводом може стати помилка з'єднання, код відповіді сервера, обрив мережі або занадто довга відповідь.
Повтор сам по собі корисний: він зменшує кількість втрачених замовлень при тимчасових збоях. Недолік такого підходу — без захисту від повторної обробки він перетворює будь-яку нестабільність мережі на дублі.
- повтор може запускатися в коді сайту або бота;
- задачу може перезапускати черга;
- запит може повторювати проксі або інтеграційний модуль;
- оператор може вручну надіслати замовлення повторно після помилки.
Повторний запит надходить раніше за першу відповідь
Іноді два однакових запити справді доходять до API майже одночасно. Наприклад, користувач двічі надіслав форму, фронтенд не заблокував кнопку або фонова задача стартувала повторно до завершення першої.
Якщо обробник спочатку перевіряє наявність замовлення, а потім створює його, дві паралельні операції можуть пройти перевірку одночасно. Кожна побачить, що замовлення ще немає, і кожна додасть новий запис.
Таку ситуацію називають гонкою даних. Проста попередня перевірка в коді не захищає від неї повністю. Недолік перевірки без обмеження на рівні бази — вона ламається при паралельному навантаженні.
Замовлення записалось, але відповідь API загубилась
Запит проходить кілька етапів: сервер отримує дані, створює запис, ставить задачу в чергу, надсилає відповідь. Збій можливий між будь-якими з них. Наприклад, база вже підтвердила створення замовлення, але з'єднання обірвалося до передачі відповіді клієнту.
Клієнт не знає, чи було прийнято замовлення, і повторює операцію. API без окремого механізму перевірки сприймає запит як новий. У журналі це часто виглядає так, ніби сервіс створив два замовлення «сам», хоча в нього було два вхідні звернення.
Ідемпотентний ключ для створення замовлення
Для операцій створення потрібен унікальний ключ ідемпотентності. Клієнт генерує його перед першим відправленням і передає разом з параметрами замовлення. При повторі через таймаут або помилку використовується той самий ключ.
API зберігає ключ разом з результатом обробки. Якщо надходить запит з уже відомим ключем, сервер не створює нове замовлення, а повертає результат першого звернення: ідентифікатор замовлення, його статус або раніше сформовану помилку.
Один ключ має відповідати одній бізнес-операції, а не одному HTTP-з'єднанню.
Недолік методу — ключі потрібно зберігати, очищати за правилами та перевіряти на боці API. Якщо генерувати новий ключ при кожному повторі, захист не спрацює. Якщо використовувати один ключ для різних замовлень, частину нових операцій буде помилково відхилено.

Унікальність має контролюватися базою даних
Ідемпотентність краще доповнювати обмеженням унікальності в базі. Для цього обирають комбінацію, яка однозначно описує замовлення: внутрішній ідентифікатор клієнта, ключ ідемпотентності, тип послуги та інші потрібні поля.
База даних має відхиляти другий запис, навіть якщо два обробники дійшли до створення одночасно. Після конфлікту API повертає наявне замовлення, а не помилку без пояснення.
Недолік жорсткого унікального обмеження — його не можна будувати лише на посиланні або username. Клієнт може свідомо замовити одну послугу на той самий канал кілька разів. Занадто широке обмеження заблокує нормальні повторні покупки.
Черга може доставити задачу більше одного разу
Черги задач часто працюють за принципом «доставка хоча б один раз». Якщо воркер обробив задачу, але не встиг підтвердити її виконання, черга може видати ту саму задачу повторно іншому воркеру.
Для черги це нормальний спосіб не втратити задачу. Для створення замовлення без ідемпотентності — джерело дублів. Ідентифікатор задачі або окремий ключ операції потрібно передавати до кінцевого обробника, включно з модулем відправлення замовлення постачальнику.
Недолік вимкнення повторної доставки — при падінні воркера частина замовлень може зникнути. Безпечніше приймати можливі повтори й робити обробник стійким до них.
Дублі виникають між панеллю та постачальником
Внутрішнє замовлення може бути створене один раз, але запит до зовнішнього API надіслано двічі. Причина та сама: панель не отримала відповідь від постачальника і вирішила повторити відправлення. Якщо постачальник встиг прийняти перший запит, на його боці з'являться дві однакові заявки.
Потрібна окрема прив'язка внутрішнього замовлення до зовнішнього: ідентифікатор відправлення, ключ ідемпотентності або збережена відповідь постачальника. Не можна вважати, що захист на вході до власної панелі автоматично захистить вихідні виклики.
Недолік звірки зі стороннім API — не кожен постачальник підтримує пошук за зовнішнім ключем. Тоді доводиться фіксувати спроби відправлення й окремо розбирати невизначені статуси.
Вебхук не повинен створювати нове замовлення
Вебхуки повідомляють про зміни: замовлення прийнято, запущено, виконано, скасовано або потребує перевірки. Помилка виникає, коли обробник вебхука сприймає повідомлення як команду створити замовлення заново.
Той самий вебхук може надійти повторно. Відправник повторює доставку, якщо не отримав підтвердження, а повідомлення іноді надходять не по порядку. Обробник має знаходити наявне замовлення за зовнішнім ідентифікатором і оновлювати статус.
Недолік обробки вебхуків лише за часом отримання — пізніше повідомлення може перезаписати актуальний статус застарілим. Потрібні ідентифікатор події, версія статусу або зрозумілі правила переходів.
Які записи допоможуть знайти джерело дублів
Для розслідування недостатньо бачити лише два номери замовлень. Потрібні дані про кожен етап обробки: час запиту, ключ ідемпотентності, ідентифікатор клієнта, параметри замовлення, номер фонової задачі, відповідь зовнішнього API та спроби повторного відправлення.
- зіставляйте дублі за ключем операції, а не лише за посиланням;
- перевіряйте, чи були однакові запити в журналі вхідного API;
- дивіться, чи повторювалася задача в черзі;
- відокремлюйте створення внутрішнього замовлення від відправлення постачальнику;
- зберігайте зовнішній ідентифікатор заявки одразу після отримання відповіді.
Недолік занадто коротких логів — джерело проблеми зникає раніше, ніж його встигають розібрати. Недолік надмірного логування — у запис можуть потрапити токени, персональні дані та інші чутливі поля, тому їх потрібно маскувати.
Як обробляти невизначений результат запиту
Після таймауту не можна одразу створювати замовлення повторно з новими даними. Спочатку API має перевірити операцію за ключем ідемпотентності або клієнтським ідентифікатором. Якщо замовлення знайдено, повертається його поточний стан. Якщо обробка ще триває, клієнт отримує статус очікування.
- Створити ключ операції до першого запиту.
- Надсилати той самий ключ при кожному повторі.
- Зберегти ключ і замовлення в одній захищеній операції бази даних.
- Передавати ідентифікатор операції в чергу та зовнішній API.
- Повертати раніше створене замовлення при повторному зверненні.
Такий сценарій потребує доопрацювання API і клієнтської інтеграції. Його недолік — складніше налагодження і більше станів замовлення, зате повторна доставка запиту перестає автоматично означати повторну покупку.
Останні статті
Що змінилося в дизайні та функціоналі Ми оновили сайт, щоб працювати з ним було швидше та зручніше. Основні зміни стосуються інтерфейсу, особистого к..
Доброго времени суток, собрал все новости за это время:1. Главная новость - сильно снижены цены на твич зрителей, пока твич откатил почти все защиты, ..
1. Використовуйте промокод "December2025" на 15% знижки для всіх наших глядачів2. Ми знизили до 1 січня базові ціни на наш конфігуратор і най дешевшу ..
Послуги Twitch працюють стабільно, тому ми готові співпрацювати з командами, реселерами, власниками сервісів, ботами і багатьма іншими.Індивідуальні..
Ми повністю оновили наші послуги перегляду Twitch, і тепер вони працюють стабільно. Ми використовуємо лише якісні IP-адреси для перегляду.Нюанс поля..
Всем доброго времени суток. Сегодня мы анонсируем новую функцию - "Конфигуратор Twitch зрителей".Теперь Вы сможете сами себе собрать любой тариф для т..
Приветствую, составил гайд для стримеров, который на данный момент будет очень актуален. Сейчас ютуб и твич отключили монетизацию с просмотров из ..
Мы наконец-то разработали API Теперь нашим сайтам партнерам будет удобнее с нами работать.По обновлению максимальных тарифов на ютуб - апдейт уже на п..
У зв'язку з величезною популярністю послуг партнерства та реферальної програми ми зробили таблицю співпраці.Суть дуже проста: більше живої аудиторії –..
Наші послуги для стрімерів

Shopee
Наші послуги для контент-мейкерів









