Saga প্যাটার্ন কী?
Saga প্যাটার্ন হলো একটি মাইক্রোসার্ভিস আর্কিটেকচারে ডিস্ট্রিবিউটেড ট্রানজেকশন (distributed transaction) পরিচালনার পদ্ধতি। প্রতিটি মাইক্রোসার্ভিসের নিজস্ব ডাটাবেস থাকে, তাই ঐতিহ্যবাহী ACID ট্রানজেকশন সম্ভব নয়। Saga প্যাটার্ন এই সমস্যার সমাধান করে একাধিক লোকাল ট্রানজেকশনকে একটি সিকোয়েন্সে সাজিয়ে, যেখানে প্রতিটি ধাপ সফল হলে পরবর্তী ধাপ চলে, এবং কোনো ধাপ ব্যর্থ হলে পূর্ববর্তী ধাপগুলোর জন্য কম্পেনসেটিং ট্রানজেকশন (compensating transaction) চালু হয়।
Saga প্যাটার্নের ধরন
Saga প্যাটার্ন দুইভাবে বাস্তবায়ন করা যায়:
- Choreography-based Saga – প্রতিটি সার্ভিস নিজেই পরবর্তী সার্ভিসকে ইভেন্টের মাধ্যমে ট্রিগার করে। কোনো কেন্দ্রীয় অর্কেস্ট্রেটর নেই।
- Orchestration-based Saga – একটি কেন্দ্রীয় অর্কেস্ট্রেটর সার্ভিস থাকে যা প্রতিটি ধাপের অর্ডার নিয়ন্ত্রণ করে এবং ব্যর্থতার ক্ষেত্রে কম্পেনসেশন চালায়।
Choreography-based Saga উদাহরণ (Java)
নিচে একটি অর্ডার ম্যানেজমেন্ট সিস্টেমের সরল উদাহরণ দেওয়া হলো। প্রতিটি সার্ভিস OrderPlaced ইভেন্ট পাবলিশ করে এবং পরবর্তী সার্ভিস সেই ইভেন্ট সাবস্ক্রাইব করে।
// OrderService.java
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
private final ApplicationEventPublisher eventPublisher;
public OrderService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void placeOrder(Order order) {
// অর্ডার সংরক্ষণ
order.setStatus("PENDING");
saveOrder(order);
// ইভেন্ট পাবলিশ করা
eventPublisher.publishEvent(new OrderPlacedEvent(order.getId()));
}
private void saveOrder(Order order) {
// ডাটাবেসে সেভ করার লজিক
}
}
উপরের কোডে, OrderService অর্ডার প্লেস করার পর একটি OrderPlacedEvent পাবলিশ করে। অন্য সার্ভিস (যেমন PaymentService) এই ইভেন্ট শুনে তার নিজস্ব ট্রানজেকশন সম্পাদন করে।
// PaymentService.java
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class PaymentService {
@EventListener
public void handleOrderPlaced(OrderPlacedEvent event) {
// পেমেন্ট প্রসেস করা
System.out.println("Processing payment for order: " + event.getOrderId());
// সফল হলে PaymentCompletedEvent পাবলিশ করা
}
}
PaymentService ইভেন্ট হ্যান্ডলার মেথডের মাধ্যমে অর্ডার ইভেন্ট গ্রহণ করে। পেমেন্ট সফল হলে এটি নিজের ইভেন্ট (PaymentCompletedEvent) পাবলিশ করবে, যা পরবর্তীতে InventoryService ট্রিগার করবে। এইভাবে একটি চেইন তৈরি হয়।
Orchestration-based Saga উদাহরণ (Java)
অর্কেস্ট্রেশন পদ্ধতিতে একটি কেন্দ্রীয় OrderSagaOrchestrator সার্ভিস থাকে যা প্রতিটি ধাপের জন্য রিমোট কল (REST/HTTP) বা মেসেজ সার্ভিস ব্যবহার করে।
// OrderSagaOrchestrator.java
import org.springframework.stereotype.Service;
@Service
public class OrderSagaOrchestrator {
private final PaymentServiceClient paymentClient;
private final InventoryServiceClient inventoryClient;
private final NotificationServiceClient notificationClient;
public OrderSagaOrchestrator(PaymentServiceClient paymentClient,
InventoryServiceClient inventoryClient,
NotificationServiceClient notificationClient) {
this.paymentClient = paymentClient;
this.inventoryClient = inventoryClient;
this.notificationClient = notificationClient;
}
public void executeSaga(Order order) {
try {
// ধাপ ১: পেমেন্ট প্রসেস
paymentClient.processPayment(order);
// ধাপ ২: ইনভেন্টরি রিজার্ভ
inventoryClient.reserveItem(order);
// ধাপ ৩: নোটিফিকেশন পাঠানো
notificationClient.sendConfirmation(order);
} catch (Exception e) {
// ব্যর্থ হলে কম্পেনসেটিং অ্যাকশন
compensatingActions(order);
}
}
private void compensatingActions(Order order) {
// কম্পেনসেটিং ট্রানজেকশন: পেমেন্ট রিফান্ড, ইনভেন্টরি আনরিজার্ভ ইত্যাদি
paymentClient.refund(order);
inventoryClient.unreserveItem(order);
}
}
এই কোডে, OrderSagaOrchestrator একটি নির্দিষ্ট ক্রমে বিভিন্ন সার্ভিসকে কল করে। যদি কোনো ধাপ ব্যর্থ হয়, তাহলে catch ব্লকের ভেতরে compensatingActions() মেথডটি পূর্ববর্তী ধাপগুলোর প্রভাব উল্টে দেওয়ার জন্য দায়ী থাকবে।
Saga প্যাটার্নের সুবিধা ও সীমাবদ্ধতা
সুবিধা:
- মাইক্রোসার্ভিসগুলো স্বাধীন থাকে এবং নিজস্ব ডাটাবেস ব্যবহার করতে পারে।
- একাধিক সার্ভিস জুড়ে তথ্যের সঙ্গতি (consistency) বজায় রাখা যায়।
- ব্যর্থতা সহনশীলতা (failure resilience) বাড়ে, কারণ কম্পেনসেটিং ট্রানজেকশন পূর্ববর্তী অবস্থা ফিরিয়ে আনে।
সীমাবদ্ধতা:
- কম্পেনসেটিং ট্রানজেকশন ডিজাইন করা জটিল হতে পারে, বিশেষ করে যখন একাধিক সার্ভিস জড়িত।
- ইভেন্টুয়াল কনসিস্টেন্সি (eventual consistency) মডেল ব্যবহার করে, তাই তাৎক্ষণিক ডেটা সঠিকতা নিশ্চিত করা যায় না (ACID নয়)।
- ডিবাগিং এবং মনিটরিং কঠিন হতে পারে, কারণ ট্রানজেকশন একাধিক সার্ভিস জুড়ে ছড়িয়ে থাকে।
সংক্ষেপে
Saga প্যাটার্ন মাইক্রোসার্ভিস পরিবেশে দীর্ঘস্থায়ী ডিস্ট্রিবিউটেড ট্রানজেকশন (long-running transactions) পরিচালনার একটি প্রমাণিত উপায়। Choreography ও Orchestration – দুই ধরনের বাস্তবায়নের মধ্যে আপনার প্রয়োজন অনুযায়ী বেছে নিন। চাইলে স্প্রিং বুটের ইভেন্ট মেকানিজম বা মেসেজ ব্রোকার (যেমন Kafka, RabbitMQ) ব্যবহার করে সহজেই Saga বাস্তবায়ন করা যায়।