Идемпотентность в API
Почему повторный запрос не должен создавать дубль: идемпотентные методы, ключ идемпотентности и безопасные ретраи.
Проблема повтора
Клиент отправил POST /orders, сеть моргнула, ответ не дошёл. Клиент не
знает, создался заказ или нет, и повторяет запрос. Если сервер на каждый
POST создаёт новый заказ, повтор делает второй. Прошлый урок про ретраи
именно поэтому запрещал повторять POST вслепую. Решение этой проблемы и
есть идемпотентность.
Идемпотентная операция даёт один и тот же результат, сколько бы раз её ни повторили. Один заказ остаётся одним заказом, повторили запрос или нет.
Какие методы идемпотентны сами по себе
Из урока про HTTP-методы:
GET,PUT,DELETEидемпотентны по определению. Прочитать дважды, заменить ресурс дважды, удалить дважды — тот же итог.POSTне идемпотентен: каждый вызов создаёт новое. Именно его повтор и плодит дубли.
Поэтому где можно, выбирают идемпотентный метод. Создать ресурс с заранее
известным id можно через PUT /orders/{id}: повтор просто перезапишет тот
же заказ, а не создаст второй.
Ключ идемпотентности
Когда нужен именно POST (id выдаёт сервер), применяют idempotency key.
Клиент генерирует уникальный ключ на операцию и шлёт его в заголовке:
POST /orders
Idempotency-Key: 9f1c-44a2-...
{ "item": "book", "qty": 1 }
Сервер запоминает обработанные ключи. Пришёл запрос с уже виденным ключом, и сервер не создаёт новый заказ, а возвращает результат первого. Повтор безопасен: тот же ключ, тот же заказ. Так делают платёжные API, где дубль это списанные дважды деньги.
1-й запрос: ключ новый → создаём заказ, сохраняем (ключ → заказ)
2-й запрос: ключ виден → возвращаем тот же заказ, ничего не создаём
Ключи хранят с истечением (например, сутки): дольше держать незачем, а повторы приходят в пределах коротких ретраев.
Зачем это вместе с ретраями
Идемпотентность и ретраи работают в паре. Ретрай из прошлого урока
повторяет неудавшийся запрос, а идемпотентность гарантирует, что повтор не
навредит. Без идемпотентности ретрай POST опасен; с ключом идемпотентности
его можно безопасно повторять, как GET.
То же касается обработчиков очередей: сообщение может прийти повторно (at-least-once доставка), и обработчик должен быть идемпотентным, иначе одно событие применится дважды.
Что важно запомнить
Повтор запроса не должен создавать дубль. GET, PUT, DELETE
идемпотентны сами; где можно, создание делают через PUT с известным id.
Для POST применяют idempotency key: сервер запоминает ключ и на повтор
возвращает результат первого вызова, не создавая новое. Так защищают
платежи и заказы.
Идемпотентность делает ретраи безопасными и обязательна для обработчиков очередей с доставкой at-least-once.
Этим закрывается трек про паттерны приложения: graceful shutdown, health-эндпоинты, конфиг, устойчивость и идемпотентность.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс