प्रॉम्प्ट और दायरा
एक क्लाइंट create-order कमांड भेजता है। सर्वर ऑर्डर को कमिट कर सकता है, और फिर रिस्पॉन्स भेजने से पहले कनेक्शन खो सकता है। क्लाइंट परिणाम नहीं जान सकता है और उसी Idempotency-Key के साथ पुनः प्रयास करता है। अनुरोध अनुबंध (request contract), ड्यूरेबल रिकॉर्ड, समवर्ती नियंत्रण (concurrency control), और रिकवरी फ़्लो को डिज़ाइन करें, और बताएं कि किन विफलताओं का पुनः प्रयास करना सुरक्षित है। मुख्य कौशल साइड-इफ़ेक्ट सीमाएं, अटॉमिकिटी और व्याख्या योग्य विफलता स्थितियां हैं, इसलिए यह बैकएंड से संबंधित है।
साक्षात्कारकर्ता क्या मूल्यांकन करता है
एक मजबूत उत्तर "अनुरोध कभी नहीं पहुंचा," "पूरा हुआ लेकिन रिस्पॉन्स खो गया," और "अभी भी प्रोसेस हो रहा है" को अलग करता है, फिर रीप्ले, स्थिति खोज (status lookup), या प्रगति-रत (in-progress) रिस्पॉन्स चुनता है। यह केवल "Redis में कुंजी डाल दें" कहने के बजाय समान-कुंजी/विभिन्न-पैरामीटर, समवर्ती पहले अनुरोध, स्टोरेज विफलता, समाप्ति, मल्टी-रीजन रूटिंग और डाउनस्ट्रीम प्रभावों को भी कवर करता है।
पहले स्पष्ट करने योग्य प्रश्न
- क्या कुंजी एक तार्किक कमांड के लिए क्लाइंट द्वारा जनरेट की गई है, या व्यावसायिक फ़ील्ड्स से सर्वर द्वारा प्राप्त की गई है?
- कौन से अनुरोध फ़ील्ड कुंजी से बंधे हैं, और कौन सा एरर बेमेल (mismatch) को दर्शाता है?
- क्या ऑर्डर राइट और idempotency रिकॉर्ड एक ही डेटाबेस ट्रांज़ैक्शन में हैं? क्या भुगतान का अपना स्वयं का idempotency अनुबंध है?
- क्लाइंट कितनी देर तक प्रतीक्षा कर सकता है, कुंजी को कितने समय तक बनाए रखा जाता है, और क्या समाप्ति से दूसरा ऑर्डर बन सकता है?
- क्या सेवा सिंगल-रीजन है या मल्टी-रीजन, और प्रत्येक इनग्रेस पथ के लिए कौन सा स्टोर आधिकारिक (authoritative) है?
30-सेकंड उत्तर रूपरेखा
"क्लाइंट एक तार्किक कमांड के लिए एक स्थिर कुंजी बनाता है और पुनः प्रयासों पर इसका पुन: उपयोग करता है। सर्वर टेनेंट, ऑपरेशन और कुंजी पर एक ड्यूरेबल विशिष्टता बाधा (uniqueness constraint) लागू करता है, जिसमें अनुरोध फ़िंगरप्रिंट, स्थिति और अंतिम रिस्पॉन्स संग्रहीत होता है। पहला अनुरोध अटॉमिक रूप से processing का दावा करता है और ऑर्डर ट्रांज़ैक्शन चलाता है; समान-कुंजी/समान-पैरामीटर अनुरोध प्रतीक्षा करते हैं या रीप्ले होते हैं, जबकि बेमेल को अस्वीकार कर दिया जाता है। क्रैश के बाद, ट्रांज़ैक्शन और डाउनस्ट्रीम साक्ष्यों से रिकवर करें। क्षतिपूर्ति (compensating) करने से पहले अज्ञात साइड इफ़ेक्ट्स की जांच करें, कभी भी आंख मूंदकर पुनः प्रयास न करें। प्रतिधारण (retention) पुनः प्रयास विंडो को कवर करना चाहिए, और मेट्रिक्स को शून्य डुप्लिकेट साइड इफ़ेक्ट्स साबित करना चाहिए।"
चरण-दर-चरण समाधान
अनुबंध के लिए एक गैर-रिक्त, सीमित कुंजी की आवश्यकता होनी चाहिए जो एक तार्किक कमांड के पुनः प्रयासों में अपरिवर्तित रहे। सर्वर एक सामान्यीकृत अनुरोध हैश, स्थिति, संसाधन आईडी, रिस्पॉन्स कोड, रिस्पॉन्स बॉडी और समाप्ति के साथ एक अद्वितीय (tenant_id, operation, idempotency_key) संग्रहीत करता है। हैश किसी भिन्न कमांड के लिए किसी कुंजी के आकस्मिक पुन: उपयोग को रोकता है।
पहले अनुरोध को एक ड्यूरेबल processing रिकॉर्ड डालना चाहिए और एक स्थानीय ट्रांज़ैक्शन में ऑर्डर बनाना चाहिए, या एक ट्रांज़ैक्शन लॉग का उपयोग करना चाहिए जो दोनों को स्पष्ट रूप से जोड़ता है। विशिष्टता संघर्ष पर, मौजूदा रिकॉर्ड पढ़ें: succeeded के लिए सहेजे गए रिस्पॉन्स को रीप्ले करें, failed के लिए वही व्यावसायिक एरर लौटाएं, और processing के लिए संक्षेप में प्रतीक्षा करें या प्रगति-रत लौटाएं। केवल इन-मेमरी लॉक पुनरारंभ (restart) और रेप्लिका में विफल हो जाता है।
समवर्तीता का निर्णय विशिष्टता बाधा और सशर्त अपडेट द्वारा किया जाता है। केवल निर्माण रिकॉर्ड का स्वामी अनुरोध ही processing को succeeded में ले जा सकता है; अपडेट में एक संस्करण या अपेक्षित स्थिति शामिल करें ताकि दो वर्कर्स कमिट न कर सकें। यदि प्रोसेस क्रैश से पहले ऑर्डर ट्रांज़ैक्शन सफल रहा, तो पुनः प्रयास succeeded पढ़ता है और इसे रीप्ले करता है। यदि ट्रांज़ैक्शन रोल बैक हो गया, तो पुनः प्रयास सुरक्षित रूप से निष्पादित हो सकता है।
डाउनस्ट्रीम प्रभाव एक ऐसी विंडो बनाते हैं जहां स्थानीय परिणाम अज्ञात होता है जबकि रिमोट प्रभाव सफल हो सकता है। भुगतान, शिपिंग और संदेशों को डाउनस्ट्रीम idempotency अनुबंध के साथ समान व्यावसायिक ऑपरेशन आईडी का उपयोग करना चाहिए, और अनुरोध और परिणाम को बनाए रखना चाहिए। डाउनस्ट्रीम idempotency के बिना, समाधान (reconciliation) की क्वेरी करें या आउटबॉक्स के माध्यम से प्रकाशित करें और एक वर्कर से पुनः प्रयास करें; केवल इसलिए दोबारा शुल्क न लें क्योंकि स्थानीय कॉल का समय समाप्त (timed out) हो गया था।
प्रगति-रत रिकॉर्ड को रिकवरी की आवश्यकता होती है। एक लीज और हार्टबीट स्टोर करें; एक रिकवरी वर्कर अंतिम स्थिति में आगे बढ़ने से पहले ऑर्डर ट्रांज़ैक्शन, डाउनस्ट्रीम स्थिति या ट्रांज़ैक्शन लॉग की जांच करता है। यदि साक्ष्य अपर्याप्त हैं, तो इसे विफलता मानने के बजाय unknown चिह्नित करें और इसे समाधान के लिए भेजें। स्टेट मशीन को succeeded को वापस processing में नहीं ले जाना चाहिए।
समाप्ति व्यावसायिक जोखिम से मेल खानी चाहिए। अधिकतम क्लाइंट पुनः प्रयास, नेटवर्क पुनः प्रयास कतार और क्षतिपूर्ति विंडो के माध्यम से रिकॉर्ड को बनाए रखें। समाप्त हो चुकी कुंजी का पुन: उपयोग करने पर एक स्पष्ट key_expired वापस आना चाहिए, न कि चुपचाप दूसरा ऑर्डर बनना चाहिए। पुराने रिस्पॉन्स निकायों को केवल तभी कॉम्पैक्ट किया जा सकता है जब ऑडिट डाइजेस्ट और संसाधन-स्तरीय विशिष्टता बनी रहे।
मल्टी-रीजन परिनियोजन में, एक तार्किक कुंजी को एक आधिकारिक स्टोर पर रूट करें या सिंक्रोनस प्रतिकृति (synchronous replication) के साथ वैश्विक विशिष्टता बाधा लागू करें। केवल इसलिए किसी अन्य रेप्लिका पर दोबारा निष्पादित न करें क्योंकि processing पढ़ने में देरी हुई है। मुख्य संघर्षों, पैरामीटर संघर्षों, प्रगति-रत टाइमआउट, रीप्ले रिस्पॉन्स, अज्ञात स्थितियों, डुप्लिकेट-संसाधन ब्लॉकों और समाधान अंतरों को मापें।
मॉडल उच्च-गुणवत्ता वाला उत्तर
"मैं एक idempotency key को एक तार्किक निर्माण कमांड की स्थिर पहचान के रूप में परिभाषित करता हूं, न कि प्रत्येक HTTP पुनः प्रयास पर एक नई अनुरोध आईडी। सर्वर टेनेंट, ऑपरेशन और कुंजी पर एक ड्यूरेबल विशिष्टता बाधा लागू करता है, जिसमें अनुरोध हैश, स्थिति, संसाधन आईडी, रिस्पॉन्स और समाप्ति संग्रहीत होती है। पहला अनुरोध अटॉमिक रूप से processing का दावा करता है और ऑर्डर बनाता है; समान-कुंजी/समान-पैरामीटर अनुरोध रीप्ले होते हैं या प्रतीक्षा करते हैं, और बेमेल को अस्वीकार कर दिया जाता है।
मैं ऑर्डर राइट और idempotency रिकॉर्ड को एक ट्रांज़ैक्शन में रखता हूं और भुगतान या अन्य डाउनस्ट्रीम प्रभावों के लिए समान ऑपरेशन आईडी पास करता हूं। यदि रिस्पॉन्स खो जाता है, तो पुनः प्रयास संग्रहीत परिणाम पढ़ता है; यदि स्थानीय स्थिति अज्ञात है, तो मैं दूसरे POST के साथ अनुमान लगाने के बजाय डाउनस्ट्रीम और समाधान रिकॉर्ड्स की जांच करता हूं। एक लीज़्ड वर्कर अटके हुए processing को रिकवर करता है, और सशर्त ट्रांज़िशन केवल succeeded, failed, या unknown की ओर ले जाते हैं। प्रतिधारण पुनः प्रयासों और क्षतिपूर्ति को कवर करता है। मैं समवर्ती पहले अनुरोधों, प्रोसेस क्रैश, खोए हुए रिस्पॉन्स और क्रॉस-रीजन विलंब को इंजेक्ट करता हूं, और शून्य डुप्लिकेट ऑर्डर या शुल्क का दावा करता हूं।"
सामान्य गलतियाँ
- प्रत्येक पुनः प्रयास के लिए एक नई कुंजी जनरेट करना → सर्वर एक तार्किक कमांड की पहचान नहीं कर सकता → मूल कुंजी का पुन: उपयोग करें।
- केवल इन-मेमरी या सिंगल-होस्ट लॉक का उपयोग करना → पुनरारंभ और रेप्लिका डुप्लीकेशन रोकथाम खो देते हैं → ड्यूरेबल विशिष्टता लागू करें।
- किसी भिन्न पेलोड के लिए परिणाम रीप्ले करना → क्लाइंट बग छुपाएं → फ़िंगरप्रिंट स्टोर करें और बेमेल को अस्वीकार करें।
processingरिकॉर्ड करने के तुरंत बाद डाउनस्ट्रीम कॉल करना → क्रैश होने से प्रभाव अज्ञेय रह जाता है → ट्रांज़ैक्शन, आउटबॉक्स, या डाउनस्ट्रीम idempotency का उपयोग करें।- टाइमआउट के बाद फिर से शुल्क लेना → रिमोट शुल्क सफल हो सकता है → पहले जांचें और समाधान करें।
- अटके हुए रिकॉर्ड को विफल मानना और फिर से चलाना → दूसरा संसाधन बनाना → रिकवरी में साक्ष्य इकट्ठा करें।
- कुंजियों को बहुत जल्दी समाप्त करना → विलंबित पुनः प्रयास डुप्लिकेट बनाते हैं → जोखिम और पुनः प्रयास विंडो के साथ प्रतिधारण को संरेखित करें।
- केवल सीरियल कॉल्स का परीक्षण करना → रेस स्थितियां अभी भी डबल-राइट करती हैं → समान-कुंजी समवर्तीता, क्रैश और मल्टी-रीजन रूटिंग का परीक्षण करें।
अनुवर्ती प्रश्न और उत्तर
अनुवर्ती 1: ऑर्डर आईडी को अद्वितीय कुंजी के रूप में क्यों न उपयोग करें?
ऑर्डर आईडी आमतौर पर सर्वर द्वारा संसाधन बनाने के बाद ही मौजूद होती है, इसलिए यह पहले रिस्पॉन्स से पहले की विंडो को कवर नहीं कर सकती है। Idempotency key साइड इफ़ेक्ट से पहले मौजूद होती है और पुनः प्रयासों को एक तार्किक कमांड से बांधती है।
अनुवर्ती 2: यदि पेलोड उसी कुंजी के साथ बदल जाए तो क्या होगा?
सामान्यीकृत बॉडी और प्रासंगिक हेडर को हैश करें। एक भिन्न फ़िंगरप्रिंट नए साइड इफ़ेक्ट के बिना पैरामीटर-संघर्ष एरर लौटाता है; क्लाइंट को नए कमांड के लिए एक नई कुंजी बनानी होगी।
अनुवर्ती 3: यदि पहला अनुरोध हमेशा के लिए processing में रहता है तो क्या होगा?
लीज़, हार्टबीट और टाइमआउट स्कैन का उपयोग करें। एक रिकवरी वर्कर स्थानीय ट्रांज़ैक्शन, डाउनस्ट्रीम परिणाम और संदेश लॉग की जांच करता है; केवल पर्याप्त साक्ष्य ही स्थिति को आगे बढ़ाते हैं, अन्यथा यह समाधान के लिए unknown बन जाता है।
अनुवर्ती 4: क्या Redis एकमात्र idempotency स्टोर हो सकता है?
यदि डेटाबेस के पास साइड इफ़ेक्ट का स्वामित्व है, तो Redis निष्कासन (eviction), विफलता या प्रतिकृति अंतराल सुरक्षा सीमा को हटा सकता है। Redis अल्पकालिक कार्य का समन्वय कर सकता है, लेकिन अंतिम स्थिति और विशिष्टता व्यावसायिक राइट के साथ सुसंगत ड्यूरेबल स्टोरेज से संबंधित है।
अनुवर्ती 5: कुंजी समाप्त होने के बाद क्या होना चाहिए?
पुरानी कुंजी को चुपचाप स्वीकार न करें। एक समाप्ति एरर लौटाएं और क्लाइंट को मूल ऑर्डर की क्वेरी करने या एक नया कमांड बनाने के लिए निर्देशित करें; संसाधन-स्तरीय व्यावसायिक विशिष्टता को एक और सुरक्षा प्रदान करनी चाहिए।
अनुवर्ती 6: आप कैसे साबित करते हैं कि डुप्लिकेट प्रभाव अनुपस्थित हैं?
एक ही कुंजी को समवर्ती रूप से भेजें, कमिट से पहले और बाद में प्रोसेस को समाप्त (kill) करें, रिस्पॉन्स खोएं और डाउनस्ट्रीम कॉल का समय समाप्त करें। संसाधन विशिष्टता, ऑपरेशन आईडी, रीप्ले किए गए रिस्पॉन्स, स्टेट-ट्रांज़िशन लॉग और समाधान की जांच करें। अभिकथन यह है कि प्रति तार्किक कुंजी अधिकतम एक सफल साइड इफ़ेक्ट हो।
अनुवर्ती 7: क्या idempotency key सटीक रूप से एक बार (exactly-once) प्रोसेसिंग है?
नहीं। यह एक सेवा को डुप्लिकेट कमांड को पहचानने योग्य बनाता है; यह क्रॉस-सर्विस नेटवर्क को exactly-once नहीं बनाता है। स्पष्ट unknown परिणामों के साथ, ट्रांज़ैक्शन, आउटबॉक्स डिलीवरी, डाउनस्ट्रीम idempotency, क्वेरी और समाधान की अभी भी आवश्यकता है।