Вопрос проверяет понимание механизмов обеспечения идемпотентности в распределенных системах для предотвращения двойных списаний при повторных запросах.
Идемпотентность — это свойство операции, при котором многократное выполнение одного и того же запроса приводит к тому же результату, что и однократное выполнение. В контексте списания средств это критически важно: если клиент отправил запрос, но не получил ответ из-за таймаута, он может повторить запрос. Без идемпотентности это приведет к двойному списанию.
Самый распространенный подход — использование уникального ключа идемпотентности (idempotency key). Клиент генерирует уникальный идентификатор (например, UUID) для каждого запроса на списание и передает его в заголовке или теле запроса. Сервер хранит этот ключ вместе с результатом операции (успех или ошибка). При повторном запросе с тем же ключом сервер проверяет, есть ли уже запись, и если да — возвращает сохраненный результат, не выполняя операцию заново.
const express = require('express');
const app = express();
app.use(express.json());
// Хранилище ключей идемпотентности (в реальности — Redis или БД)
const idempotencyStore = new Map();
app.post('/withdraw', async (req, res) => {
const { idempotencyKey, amount, accountId } = req.body;
// Проверяем, был ли уже обработан запрос
if (idempotencyStore.has(idempotencyKey)) {
return res.status(200).json(idempotencyStore.get(idempotencyKey));
}
// Выполняем списание (например, через внешний API)
try {
const result = await processWithdrawal(accountId, amount);
idempotencyStore.set(idempotencyKey, { success: true, transactionId: result.id });
res.status(200).json({ success: true, transactionId: result.id });
} catch (error) {
// В случае ошибки тоже сохраняем, чтобы не повторять
idempotencyStore.set(idempotencyKey, { success: false, error: error.message });
res.status(500).json({ success: false, error: error.message });
}
});В распределенных системах ключи идемпотентности должны храниться в надежном и быстром хранилище, доступном всем экземплярам сервиса. Обычно для этого используют Redis с TTL (временем жизни) или базу данных с уникальным индексом на поле ключа. TTL позволяет автоматически очищать старые ключи, чтобы хранилище не переполнялось.
Идемпотентность через ключи — это стандартный и надежный способ защиты от двойных списаний в распределенных системах. Его следует применять везде, где возможны повторные запросы из-за таймаутов или сбоев сети, особенно в финансовых операциях, платежных системах и любых критических транзакциях.
Frontend developer
Ментор по Frontend
Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства
Записаться на консультацию