1. प्रश्न
उपयोगकर्ता द्वारा ऑर्डर सबमिट करने के बाद, इन्वेंट्री, पेमेंट, डिलीवरी और कूपन सर्विसेज़ को पूर्ति पूरी करनी होगी। बिज़नेस नियम या नेटवर्क ख़राबी के कारण कोई भी चरण विफल हो सकता है, और कमिट किए गए रिमोट ट्रांज़ैक्शन को रोल बैक नहीं किया जा सकता है। एक Saga डिज़ाइन करें जो CONFIRMED या CANCELLED में समाप्त होता है, और प्रत्येक लोकल ट्रांज़ैक्शन व कम्पेंसेशन की व्याख्या करें।
2. बाधाएं और स्पष्टीकरण
- प्रत्येक सर्विस केवल अपने डेटाबेस के विरुद्ध एक लोकल ACID ट्रांज़ैक्शन चलाती है।
- इवेंचुअल कंसिस्टेंसी स्वीकार्य है, लेकिन इन्वेंट्री और पेमेंट होल्ड हमेशा के लिए नहीं रह सकते।
- पुनः प्रयास (Retries) किसी चरण को एक से अधिक बार निष्पादित कर सकते हैं; सर्विसेज़ को आइडेम्पोटेंसी keys के साथ स्थिति की रक्षा करनी चाहिए।
- पुनः प्रयास योग्य तकनीकी विफलताओं, गैर-पुनः प्रयास योग्य बिज़नेस अस्वीकृतियों, और मानवीय हस्तक्षेप की आवश्यकता वाली कम्पेंसेशन विफलताओं के बीच अंतर करें।
3. मुख्य दृष्टिकोण
एक Saga किसी लंबे ट्रांज़ैक्शन को क्रमित लोकल ट्रांज़ैक्शन्स T1 ... Tn में विभाजित करता है। प्रत्येक सफल चरण प्रगति को रिकॉर्ड करता है और अगले को ट्रिगर करता है; यदि बाद का कोई चरण विफल हो जाता है, तो पूर्ण हो चुके चरण उल्टे क्रम में कम्पेंसेशन Ck ... C1 चलाते हैं। कम्पेंसेशन डेटाबेस रोलबैक के बजाय एक नया बिज़नेस ऑपरेशन होता है, जैसे इन्वेंट्री रिलीज़ करना, पेमेंट ऑथराइज़ेशन रद्द करना, डिलीवरी कैंसल करना या कूपन वापस करना।
एक ऑर्केस्ट्रेटेड Saga में एक ड्यूरेबल कोऑर्डिनेटर होता है जो स्थिति और अगले एक्शन को स्टोर करता है, जो स्पष्ट वर्कफ़्लो, टाइमआउट और मानवीय हस्तक्षेप की आवश्यकताओं के अनुकूल होता है। इवेंट-संचालित कोरियोग्राफी केंद्रीय कोऑर्डिनेटर को हटा देती है लेकिन दृश्यता और चक्र नियंत्रण (cycle control) को कठिन बना देती है। किसी भी शैली में, प्रत्येक कमांड और इवेंट पर saga_id, step_id, वर्ज़न और आइडेम्पोटेंसी key शामिल करें।
4. संदर्भ कार्यान्वयन
start(order):
saga = create_saga(order.id, state="RESERVE_STOCK")
dispatch(saga, "ReserveStock")
on_step_result(saga_id, step_id, result):
saga = load_and_lock(saga_id)
require result.version == saga.version + 1
if result.success:
saga.completed_steps.append(step_id)
saga.version += 1
next = next_step(saga)
persist(saga)
dispatch(next) if next else finish_confirmed(saga)
else if result.business_rejection:
saga.state = "COMPENSATING"
persist(saga)
dispatch(compensation_for_last_completed(saga))
else:
schedule_retry_or_timeout(saga, step_id)
on_compensation_result(saga_id, step_id, result):
record_attempt(saga_id, step_id, result)
if result.success:
dispatch(previous_compensation(saga))
else:
mark_manual_intervention(saga, reason=result.error)5. कंसिस्टेंसी और शुद्धता
कोऑर्डिनेटर स्थिति ड्यूरेबल होनी चाहिए अन्यथा क्रैश होने पर अगला एक्शन खो सकता है। प्रत्येक कमांड और इवेंट एक आइडेम्पोटेंसी key का उपयोग करता है; उपभोक्ता अपने बिज़नेस परिवर्तन को कमिट करने से पहले एक प्रोसेस्ड step_id रिकॉर्ड करता है, जिससे पुनः प्रयास को इन्वेंट्री दो बार रिज़र्व करने से रोका जा सके। किसी चरण को पूरा करने और अगले कमांड को प्रकाशित करने के बीच एक सेंड गैप (send gap) भी होता है, इसलिए इवेंचुअल विज़िबिलिटी के लिए एक आउटबॉक्स, विश्वसनीय कतार (queue) या CDC की आवश्यकता होती है।
कम्पेंसेशन आमतौर पर रिवर्स सफलता क्रम में चलता है, लेकिन प्रत्येक एक्शन का कोई सटीक इनवर्स नहीं होता है। कुछ प्रभावों के लिए बिज़नेस एडजस्टमेंट की आवश्यकता होती है, जैसे पहले से भेजे गए नोटिफिकेशन को वापस लेने के बजाय रिफंड देना। स्टेटस क्वेरीज़ को "प्रोसेसिंग" को सफलता के रूप में रिपोर्ट करने के बजाय वर्तमान चरण, पूर्ण किए गए चरण, पुनः प्रयास गणना और मानवीय हस्तक्षेप के कारण को प्रदर्शित करना चाहिए।
6. फॉलो-अप और संभावित ख़ामियां
- Saga को विभिन्न डेटाबेसों में एटॉमिक रोलबैक के रूप में वर्णित न करें; यह पुनः प्राप्त करने योग्य (recoverable) इवेंचुअल कंसिस्टेंसी प्रदान करता है।
- कम्पेंसेशन भी विफल हो सकता है, इसलिए एक अनंत ऑटोमैटिक लूप के बजाय पुनः प्रयास, डेड लेटर्स, अलर्ट्स और मानवीय हस्तक्षेप (human takeover) जोड़ें।
- एक ग्लोबल डिस्ट्रीब्यूटेड लॉक विफलता डोमेन का विस्तार करता है और रिमोट बिज़नेस कमिट को पूर्ववत नहीं कर सकता है।
- इन्वेंट्री और पेमेंट होल्ड के लिए TTL परिभाषित करें; Saga समाप्त होने पर उन्हें टाइमर या इवेंट के साथ रिलीज़ करें।
7. आगे पढ़ना
ऑर्केस्ट्रेशन की तुलना कोरियोग्राफी से करें: ऑर्केस्ट्रेशन स्थिति, क्रम और टाइमआउट को केंद्रीकृत करता है, जबकि कोरियोग्राफी इवेंट्स के माध्यम से सर्विसेज़ को डीकपल करती है लेकिन एंड-टू-एंड ट्रेसिंग को कठिन बना देती है। गैर-कम्पेंसेटेबल साइड इफेक्ट्स, सिमेंटिक लॉक्स, वर्ज़न टकराव, ऑडिट लॉग्स और कब एक सिंगल डेटाबेस ट्रांज़ैक्शन सरल होता है, इस पर चर्चा करें।
8. साक्षात्कार स्कोरिंग बिंदु
लोकल ट्रांज़ैक्शन्स को विभाजित करने की क्षमता
उम्मीदवार को इन्वेंट्री, पेमेंट, डिलीवरी और कूपन चरणों को सूचीबद्ध करना चाहिए और यह बताना चाहिए कि प्रत्येक सर्विस केवल अपने लोकल ट्रांज़ैक्शन को कमिट करती है।
एक कम्पेंसेशन स्टेट मशीन डिज़ाइन करने की क्षमता
उन्हें सफलता, विफलता और रिवर्स कम्पेंसेशन पाथ दिखाने चाहिए, जिसमें बिज़नेस अस्वीकृति, तकनीकी पुनः प्रयास और मानवीय हस्तक्षेप के बीच अंतर स्पष्ट हो।
आइडेम्पोटेंसी और विश्वसनीय मैसेजिंग को संभालने की क्षमता
उन्हें कोऑर्डिनेटर क्रैश और कमांड-सेंड गैप को कवर करने के लिए saga_id, step_id, आइडेम्पोटेंसी keys और आउटबॉक्स या विश्वसनीय कतार (reliable queue) का उपयोग करना चाहिए।
बिज़नेस सीमाओं को स्पष्ट करने की क्षमता
उन्हें यह स्वीकार करना चाहिए कि कम्पेंसेशन रोलबैक नहीं है और TTL, गैर-कम्पेंसेटेबल साइड इफेक्ट्स, स्टेटस क्वेरीज़ और इवेंचुअल कंसिस्टेंसी के उपयोगकर्ता अनुभव पर चर्चा करनी चाहिए।