Идемпотентность
… То, о чем многие слышали, но стеснялись спросить 😁
Разбавим менеджерские посты и немножко попроектируем, чтобы разобраться с понятием идемпотентности.
Приведу типичный диалог с Systems Design интервью.
Делаем платёжную систему.
Пользователь хочет отправить другу 1000р.
Но вдруг дрогнула рука, и он дважды нажал кнопку «оплатить».
В итоге отправилось два запроса и с карты списалось дважды.
Что делать?
— «Давайте отключать кнопку после первого нажатия!»
Это первое, что приходит на ум. Вариант хороший с точки зрения UX, но проблему решает не полностью.
Допустим, запрос на сервер пришел, сервер его корректно обработал, но из-за сетевых проблем ответ не вернулся.
Клиент видит сообщение «что-то пошло не так, попробуйте еще раз», нажимает повторно — и списываются ещё 1000р.
— «Давайте дедуплицировать запросы по сумме и назначению!»
Вот мы и подобрались к понятию идемпотентности, но еще пока не совсем с правильной стороны.
Идемпотентность — это свойство операции, при котором повторное выполнение будет давать тот же результат, что и первое.
Простыми словами: даже если клиент отправит один и тот же запрос 10 раз, результат будет один и без дополнительных сайд-эффектов.
Казалось бы, можно пост на этом заканчивать.
Но подождите, есть еще не обработанные ситуации:
— Что, если пользователь реально хочет отправить еще тыщу?
— Что делать партнёру, который интегрировался с нашим платёжным шлюзом по API и автоматизировал выплаты своим клиентам?
Ему надо отправить 1000р сейчас и еще 1000р через минуту.
Попытки дедуплицировать по параметрам усложняют логику:
— Сколько времени хранить историю запросов?
— Что делать, если в запросе 100 параметров?
— Что если реально надо отправить подряд три транзакции по 1000р?
Ключ идемпотентности помогает решить эту проблему.
Идея простая:
1. Клиент генерирует уникальный ключ (например, UUID) для каждого запроса.
2. Все повторные попытки отправляются с этим же ключом.
3. Сервер хранит результат выполнения операции по этому ключу и возвращает его при повторных запросах.
Реализовать идемпотентность можно по-разному. Самое простое — кеширование ответов по ключу идемпотентности. Так, например, сделано у Stripe.
На картинке sequence-диаграмма с более сложным, но персистентным вариантом — ключ идемпотентности прикапывается в нашу транзакцию.
В качестве бонус-контента дам ссылку на моё любимое видео — Идемпотентность на коровах.
В двух словах — «Беременную корову нельзя осеменить повторно».
———
Надеюсь, я своими менеджерскими постами еще не всех подписчиков-технарей растерял 🙃
Надо бы почаще писать про всякое техническое.
А вы учитываете идемпотентность при проектировании?
Post #178
4.38K