Просто о сложном: идемпотентность Идемпотентность — это свойство операции, которую можно выполнить несколько раз, получая тот же результат, что и при …
Идемпотентность — это свойство операции, которую можно выполнить несколько раз, получая тот же результат, что и при однократном выполнении.
Простыми словами: повторный вызов не меняет состояние системы после первого успешного выполнения.
Классический пример — HTTP методы: GET, PUT, DELETE идемпотентны, POST — нет.
🟢 Ключевые моменты
🔘Идемпотентная операция: setStatus(ACTIVE) — сколько раз ни вызови, статус будет ACTIVE.
🔘Неидемпотентная операция: balance += 100 — каждый вызов увеличивает баланс.
🔘Идемпотентность ≠ отсутствие побочных эффектов (это чистота функций).
🔘Критична для распределённых систем: retry-механизмы, очереди сообщений, API.
🔘Защищает от дублирующих запросов при сетевых сбоях.
🟢 Под капотом
В реальных системах идемпотентность достигается через:
→ Idempotency Key — клиент генерирует уникальный ключ и передаёт в запросе. Сервер проверяет: если операция с таким ключом уже выполнялась — возвращает закешированный результат.
→ Версионирование — оптимистичные блокировки через версии записей (JPA @Version).
→ Уникальные идентификаторы — вместо "создай заказ" отправляем "создай заказ с ID=xyz". Повторный запрос с тем же ID игнорируется.
→ Статус-машины — переходы между состояниями: если уже в целевом состоянии, ничего не делаем.
🟢 Подводные камни
— Idempotency key нужно хранить ограниченное время (обычно 24 часа).
— Нужна атомарность проверки и выполнения.
— Сложность при асинхронной обработке.
— Не все бизнес-операции можно сделать идемпотентными.
— Overhead на хранение и проверку ключей.
✔️ Когда использовать
— REST API с критичными операциями (платежи, создание заказов).
— Kafka consumers — защита от повторной обработки при rebalance.
— Интеграция с внешними системами через retry.
— Scheduled jobs, которые могут запуститься дважды.
— Распределённые транзакции (Saga pattern).
— Webhook обработчики.
— Любые операции с денежными средствами.
❌ Не нужно:
— Внутренние CRUD операции без side effects.
— Операции чтения (они идемпотентны по умолчанию).
— Высоконагруженные операции, где overhead критичен.
— Простые внутренние методы без внешних вызовов.
🔧 Бонус-трюк: в Spring можно создать аннотацию @Idempotent и реализовать через AOP с использованием Redis для хранения idempotency keys. Получается декларативная идемпотентность на уровне методов.
Java библиотека