مدیریت تراکنشهای توزیعشده با الگوی Saga و RabbitMQ
مدیریت تراکنشهای توزیعشده با الگوی Saga و RabbitMQ
در یک سیستم مونولیت، اگر کاربری سفارشی ثبت کند، ما یک تراکنش دیتابیس (Transaction) میزنیم و اگر موجودی کافی نبود، کل عملیات Rollback میشود. اما در معماری میکروسرویس، دیتابیسها از هم جدا هستند. شما نمیتوانید یک تراکنش ACID بین سرویس سفارشات و سرویس پرداخت داشته باشید. اینجاست که الگوی Saga وارد میشود.
🧩 الگوی Saga چیست؟
Saga یک الگو برای مدیریت تراکنشهای توزیعشده است. به جای یک تراکنش بزرگ، ما یک سری تراکنش محلی (Local) داریم که با ارسال پیام (Event) به هم زنجیر میشوند. اگر یکی از مراحل شکست بخورد، مراحل قبلی باید یک عمل جبرانی (Compensating Transaction) انجام دهند.
🐇 چرا RabbitMQ؟
RabbitMQ با صفهای پیام (Message Queues) و قابلیت Dead Letter Exchange، ابزار عالی برای پیادهسازی Saga است. ما از الگوی Choreography استفاده میکنیم که در آن هر سرویس به رویدادهای سرویس دیگر گوش میدهد.
جریان یک سفارش (مثال واقعی):
- سرویس سفارشات پیام
OrderCreatedرا در RabbitMQ منتشر میکند. - سرویس موجودی پیام را میخواند. اگر موجودی داشت، پیام
InventoryReservedرا منتشر میکند. اگر موجودی نداشت، پیامInventoryFailedرا میفرستد. - سرویس پرداخت منتظر
InventoryReservedمیماند تا پرداخت را انجام دهد.
💻 پیادهسازی در NestJS (با پکیج @nestjs/microservices)
// سرویس سفارشات
this.client.emit('order_created', { orderId: 123, productId: 1 });
// سرویس موجودی (Listener)
@EventPattern('order_created')
async handleOrderCreated(data: any) {
const isAvailable = await this.checkStock(data.productId);
if (isAvailable) {
this.client.emit('inventory_reserved', data);
} else {
this.client.emit('inventory_failed', data);
}
}