Сохраняйте один ключ для одной задуманной операции, проверяйте параметры и атомарно закрепляйте право выполнения. Явно определите конкурентность, срок хранения и ошибки; одного заголовка недостаточно для согласования действий.
Идентифицируйте намерение, а не совпадение параметров
Две одинаковые брони могут быть намеренными, а две попытки создать одну бронь — повтором. Разбор AWS объясняет пользу идентификатора операции, который задаёт вызывающая сторона. Создайте ключ до первой попытки и сохраняйте при повторах. Изменённое бронирование — новая операция с новым ключом.
В нашей модели API область ключа включает авторизованного клиента, метод и маршрут. Сохраняйте отпечаток проверенных и нормализованных бизнес-параметров. Не определяйте владельца по недоверенному полю в теле запроса: авторизация должна исходить из подтверждённой учётной записи.
Определите договорённость о повторных запросах
Ниже — решения для нашего учебного API, а не обязательные коды ответа любого провайдера. Повторный ключ с другими параметрами не должен молча возвращать чужой результат. Ограничьте ожидание уже выполняющейся операции и опубликуйте срок, в течение которого сохранённый результат можно получить повторно. Клиенту нужны эти правила для выбора дальнейших действий.
| Запрос | Решение сервера |
|---|---|
| Новый ключ в своей области | Закрепить и выполнить |
| Готовый ключ, прежние параметры | Вернуть сохранённый результат |
| Прежний ключ, другие параметры | Отклонить переиспользование |
| Совпадающая операция выполняется | Коротко ждать или сообщить конфликт |
Закрепите право выполнения до создания брони
Проверка наличия с последующей вставкой допускает гонку: два обработчика одновременно увидят отсутствие записи. Для операции внутри базы задайте уникальное ограничение на ключ с его областью и атомарно попробуйте вставку. ON CONFLICT в PostgreSQL подходит для такой проверки. Бронь изменяет только обработчик, которому удалось закрепить ключ.
Ниже псевдокод архитектуры, а не исполняемый SQL. Запись ключа, создание брони и сохранение ответа находятся в одной транзакции. При Read Committed конкурирующая вставка может ждать другую транзакцию; после конфликта читайте завершённую запись отдельным последующим оператором. Тайм-аут ожидания блокировки нужно обработать явно, а не считать доказательством отсутствия брони.
НАЧАТЬ ТРАНЗАКЦИЮ
попробовать вставку с UNIQUE(клиент, метод, маршрут, ключ)
если запись вставлена:
создать бронь
сохранить отпечаток параметров и ответ
ЗАФИКСИРОВАТЬ
иначе:
прочитать запись следующим оператором
отклонить другие параметры или вернуть готовый ответ
ЗАФИКСИРОВАТЬГраница транзакции определяет гарантию
При откате этой транзакции не остаётся ни брони, ни её успешного результата. Если фиксация состоялась, а соединение оборвалось до ответа, совпадающий повтор читает сохранённый результат. Так разрешается неопределённость тайм-аута в нашем примере.
Внешнее списание денег или письмо не входят в транзакцию базы. Сбой после внешнего действия, но до записи успеха оставляет неизвестный результат. Используйте документированный механизм идемпотентности провайдера и сверку состояния при необходимости. Наличие одного ключа не доказывает сквозную гарантию exactly-once: границы и восстановление нужно описать отдельно.
Перед повтором изучите правила провайдера
Stripe описывает возврат первого сохранённого статуса и тела, включая ответы 500. Документация также задаёт сравнение параметров, возможность удаления ключа после как минимум 24 часов и случаи, когда ошибки проверки или конкурентный конфликт не сохраняют результат. Это правила Stripe, а не свойства любой реализации идемпотентности.
При неопределённом результате сохраняйте исходный ключ, следуйте рекомендациям провайдера и ограничивайте попытки с задержкой. После истечения хранения не считайте, что старый ключ защищает от новой операции. Сверяйте незавершённые результаты вместо генерации новых ключей до получения успеха. Иначе каждая попытка может стать самостоятельным действием.
Проверьте последовательность сбоев
Для упражнения используйте одноразовый сервис и базу. Проверяйте записи бронирований вместе с ответами. Проверка только успешного HTTP-статуса может пропустить дублирующую запись или результат, сохранённый до фиксации самой брони. Сформулируйте ожидаемое состояние до каждого опыта, чтобы успешный ответ не подменял проверку данных.
- Отправьте совпадающие запросы одновременно и проверьте одну бронь.
- Повторите ключ с другими параметрами и проверьте отказ.
- Оборвите ответ после фиксации и повторите исходный ключ.
- Отдельно проверьте откат, тайм-аут и истёкший ключ.
Коротко
Частые вопросы
Для каждого повтора нужен новый ключ?
Нет. Повтор одной задуманной операции использует исходный ключ. Новая операция получает новый ключ, даже если её бизнес-параметры совпадают с предыдущими.
Проверка кеша предотвращает конкурентные дубли?
Отдельное чтение не закрепляет выполнение атомарно. Нужен механизм с обеспеченной уникальностью и правило для конкурирующих обработчиков, пока первая операция ещё выполняется.
Ключ идемпотентности гарантирует выполнение?
Нет. Он помогает обрабатывать дубли в рамках контракта. Доступность, лимит попыток, хранение и внешние действия определяют завершение операции и способ устранения неопределённости.
Источники
Источники и редакционная политика
Сведения проверены 4 октября 2026 г. Ссылки рядом с разделами указывают источники фактов и технических объяснений. Выводы, учебные сценарии и рекомендации по подготовке — редакционная работа RecallDeck.
От чтения к воспроизведению
Отрепетируйте полный цикл интервью.
RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.