Вопрос проверяет понимание управления транзакциями в распределенных системах и сервисах, что важно для обеспечения целостности данных при выполнении нескольких операций.
Когда несколько методов должны выполняться как единое целое, требуется механизм транзакций. В монолитных приложениях это решается через базу данных с ACID-свойствами. В распределенных системах, где методы могут быть в разных сервисах, используются распределенные транзакции.
Saga — это последовательность локальных транзакций, где каждая имеет компенсирующее действие. Если один шаг завершается ошибкой, Saga запускает компенсации для отмены предыдущих шагов.
// Пример Saga на Node.js
async function createOrderSaga(orderData) {
try {
const order = await orderService.create(orderData);
const payment = await paymentService.charge(order.id, orderData.amount);
const inventory = await inventoryService.reserve(orderData.items);
return { order, payment, inventory };
} catch (error) {
// Компенсации
if (inventory) await inventoryService.release(orderData.items);
if (payment) await paymentService.refund(order.id);
if (order) await orderService.cancel(order.id);
throw error;
}
}2PC использует координатор, который сначала опрашивает участников (prepare), затем фиксирует (commit). Это обеспечивает атомарность, но снижает производительность и требует блокировок.
Для микросервисов предпочтительнее Saga, так как он не блокирует ресурсы и лучше масштабируется. 2PC подходит для критичных операций в контролируемой среде, где важна строгая согласованность.
Вывод: используйте Saga для распределенных систем с высокой нагрузкой, а 2PC — для небольших кластеров с требованиями строгой ACID.