196

Идемпотентные операции в программировании

Всем привет, работаю java разработчиком 10 лет. В широком смысле вся разработка сводится к применению операций к данным. Операции могут обладать свойствами, в этом посте я бы хотел рассказать про свойство идемпотентности.

Пусть исходными данными будет число 5, а операцией будет "умножить на 2". В зависимости от количества n применений операции будем получать разный результат:

n = 0 -> 5
n = 1 -> 10
n = 2 -> 20 и так далее

Ничего удивительного. Но если возьмем операцию "умножить на 0" то результат будет следующий:

n = 0 -> 5
n = 1 -> 0
n = 2 -> 0 и так далее

Видно, что после n = 1 результат не меняется. Свойство операции давать одинаковый результат при однократном и многократном применении называется идемпотентностью. Получается, что операция "умножить на 0" идемпотентна, а "умножить на 2" нет.

Рассмотрим более близкую к бизнесу ситуацию. За баланс пользователя сотового оператора отвечает один сервис, а обработкой платежей занимается другой. Пользователь хочет пополнить телефон, деньги с карты уже списали, и осталось дождаться когда увеличится баланс. Нужно чтобы сервис баланса выполнил операцию "зачислить пользователю Васе 100р", а поручение на это дает сервис платежей:

Подача поручения и успешный ответ

Подача поручения и успешный ответ

Но что делать сервису платежей, если он не получил положительный ответ от сервиса баланса? Сетевое подключение не стабильно, и проблема может произойти:

  • в момент отправки поручения - тогда Вася не увидит свои 100р, будет писать в техподдержку

  • в момент доставки ответа - тогда пользователь увидит зачисление

Проблема в том, что сервис платежей не может достоверно понять, было обработано поручение или нет. Он видит только что не пришел положительный ответ. Сетевые проблемы исчезают так же быстро как появляются, и можно было бы попробовать отправить поручение еще раз (retry). Но что если в первый раз поручение таки было успешно обработано, и в случае ретрая баланс пользователя будет увеличен еще раз, в сумме на 200р?

Представим что операция увеличения баланса - идемпотентная. Тогда можно было бы ретраить подачу поручения множество раз (n >= 1), и в конечном счете получить успешный ответ. При этом повторные начисления будут исключены (так как результат операции для n > 1 такой же как для n = 1).

Чтобы операция пополнения баланса стала идемпотентной, нужно сначала предусмотреть возможность установить уникальность операции. Если Вася пополнял баланс на 100р дважды - вчера и сегодня - то такие операции должны интерпретироваться как разные. Получается, можно было бы различать операции по такому набору атрибутов: {имя пользователя, сумма, дата}. Еще лучше использовать синтетический идентификатор, например id операции списания с карты.

Итак, сервис платежей, помимо бизнес атрибутов, передает технический атрибут - id. Сервис баланса запоминает id обработанных ранее поручений, и игнорирует повторную обработку, в любом случае возвращая успешный ответ. Усилиями двух сервисов операция зачисления стала идемпотентной.

Если тема показалась интересной, и есть пожелания разобрать еще что-нибудь из бекенда, пишите их в комментарии. Всем удачных проектов!

Лига программистов

2.1K постов11.9K подписчик

Правила сообщества

- Будьте взаимовежливы, аргументируйте критику

- Приветствуются любые посты по тематике программирования

- Если ваш пост содержит ссылки на внешние ресурсы - он должен быть самодостаточным. Вариации на тему "далее читайте в моей телеге" будут удаляться из сообщества

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества