प्रॉम्प्ट और संदर्भ
एक शेयर्ड कंप्यूट क्लस्टर इंटरएक्टिव जॉब्स, बैच वर्क और प्रीएम्प्टिबल ट्रेनिंग चलाता है। टेनेंट्स अस्थायी रूप से बर्स्ट (उपयोग में उछाल) कर सकते हैं, लेकिन कोई भी टेनेंट असीमित CPU, मेमोरी या GPU पर कब्जा नहीं कर सकता है। हाई-प्राथमिकता वाले काम को कम प्रतीक्षा समय की आवश्यकता होती है, जबकि कम प्राथमिकता वाले टेनेंट्स को भुखमरी (starvation) का सामना नहीं करना चाहिए।
कतारें (queues), एक रिसोर्स लेज़र, शेड्यूलिंग पॉलिसी, प्रीएम्प्शन और रिकवरी डिज़ाइन करें। Kubernetes PriorityClass, ResourceQuota और प्रीएम्प्शन को अलग रखता है; IETF कतार-प्रबंधन मार्गदर्शन भी निष्पक्षता और कंजेशन नियंत्रण को एकल वैश्विक FIFO के बजाय संबंधित बाधाओं के रूप में मानता है।
इंटरव्यूअर क्या परीक्षण कर रहा है
- टेनेंट कोटा, जॉब प्राथमिकता और नोड व्यवहार्यता को अलग करना।
- ऐसी निष्पक्षता को परिभाषित करना जो कम प्राथमिकता वाले काम को भुखमरी में न डाले।
- प्रीएम्प्शन के दुष्प्रभावों, रीट्राई प्रवर्धन और विखंडन (fragmentation) को सीमित करना।
- शेड्यूलर विफलता, डुप्लिकेट डिस्पैच और वर्कर के नुकसान से रिकवर करना।
- क्लस्टर औसत के बजाय टेनेंट-स्तरीय मेट्रिक्स के साथ निष्पक्षता साबित करना।
स्पष्टीकरण के लिए प्रश्न
- क्या संसाधन CPU, मेमोरी, GPU हैं, या लोकल डिस्क वाले विषम (heterogeneous) नोड्स हैं?
- क्या कोटा टेनेंट, प्रोजेक्ट, कतार या संगठन के दायरे में है?
- क्या प्राथमिकता काम को प्रीएम्प्ट कर सकती है, और चेकपॉइंट रिकवरी लागत क्या है?
- क्या जॉब्स को विभाजित, रद्द या पुनः प्रयास किया जा सकता है, और क्या परिणाम राइट्स इडेम्पोटेंट हैं?
- क्या निष्पक्षता मैक्स-मिन शेयर, वेटेड शेयर या प्रतीक्षा-समय की सीमा है?
तीस-सेकंड का उत्तर
मैं प्रति टेनेंट कोटा, उपयोग और समाप्त होने वाली उधार क्षमता बनाए रखूँगा, फिर जॉब्स को टेनेंट-स्तरीय कतारों में रखूँगा। नोड बाधाओं को फ़िल्टर करने के बाद, शेड्यूलर वेटेड फेयर सर्विस द्वारा सबसे कम सेवा प्राप्त टेनेंट का चयन करता है; एजिंग प्रभावी प्राथमिकता को बढ़ाती है ताकि काम भुखमरी का शिकार न हो। प्रीएम्प्शन केवल तभी अनुमत है जब पॉलिसी, कोटा और रिकवरी इसे सुरक्षित बनाते हैं। आरक्षण, लीज और फेंसिंग टोकन टिकाऊ (durable) होते हैं, और मेट्रिक्स को टेनेंट, कतार और संसाधन प्रकार के आधार पर विभाजित किया जाता है।
चरण-दर-चरण डिज़ाइन
चरण 1: संसाधन और कोटा लेज़र का निर्माण करें
CPU, मेमोरी, GPU और नोड लेबल्स को एक संसाधन वेक्टर के रूप में दर्शाएं। लंबे समय तक उपयोग टेनेंट कोटा की खपत करता है; बर्स्ट उधारी समाप्त हो जाती है। डिस्पैच से पहले संसाधनों को परमाणु रूप से (atomically) आरक्षित करें और पूरा होने, रद्द होने या लीज समाप्त होने पर उन्हें वापस लौटाएं। एडमिशन और शेड्यूलिंग पर कोटा लागू करें ताकि कोई कॉलर उच्च प्राथमिकता के साथ इसे बायपास न कर सके।
चरण 2: पदानुक्रमित कतारों और निष्पक्ष चयन का उपयोग करें
संगठन, टेनेंट और जॉब क्लास को स्तरित करें, फिर भार (weight) के अनुसार चलने योग्य टेनेंट्स में से चुनें। वर्चुअल सेवा या हाल के संसाधन उपयोग को ट्रैक करें और कम सेवा प्राप्त टेनेंट का चयन करें; प्रतीक्षा सीमा के बाद बाउंडेड एजिंग जोड़ें। एक वैश्विक प्राथमिकता कतार एक बड़े टेनेंट को हमेशा के लिए शीर्ष पर बने रहने दे सकती है, जबकि टेनेंट-स्तरीय रोटेशन निष्पक्षता सीमा को स्पष्ट बनाता है।
चरण 3: प्राथमिकता, उधारी और प्रीएम्प्शन को सीमित करें
प्राथमिकता तात्कालिकता का प्रतिनिधित्व करती है, असीमित क्षमता का नहीं। उधारी निष्क्रिय क्षमता या एक स्पष्ट विंडो तक सीमित है। प्रीएम्प्ट करने से पहले, जारी किए गए संसाधनों, चेकपॉइंट लागत और पीड़ित के बजट का अनुमान लगाएं; कम प्राथमिकता वाले रिकवर करने योग्य कार्य को प्राथमिकता दें। यदि रिकवरी स्पष्ट रूप से सुरक्षित नहीं है, तो डुप्लिकेट दुष्प्रभावों का जोखिम उठाने के बजाय तत्काल कार्य को प्रतीक्षा करने दें।
चरण 4: नोड्स को फ़िल्टर करें और विखंडन को नियंत्रित करें
नोड्स को स्कोर करने से पहले आर्किटेक्चर, GPU मॉडल, ज़ोन, एफिनिटी और क्षमता को फ़िल्टर करें। एक ही कतार में बड़े और छोटे अनुरोधों को मिलाने से विखंडन होता है; बड़े आकारों के लिए एक सीमित पूल आरक्षित करें और प्रतीक्षा सीमा निर्धारित करें। अस्वीकृति के कारणों को अलग-अलग रिकॉर्ड करें: कुल क्षमता, आकार बेमेल और समाप्त कोटा।
चरण 5: लीज और इडेम्पोटेंट रिकवरी के साथ डिस्पैच करें
एक वर्ज़न वाले आरक्षण को बनाए रखें (persist करें)। वर्कर्स एक फेंसिंग टोकन के साथ एक छोटी लीज का दावा करते हैं। डुप्लिकेट डिस्पैच की जांच (job_id, attempt) द्वारा की जाती है; केवल एक नया टोकन ही समाप्त हो चुकी लीज को टेकओवर कर सकता है। परिणाम कमिट होने के बाद आरक्षण जारी करें। शेड्यूलर पुनरारंभ होने पर, मेमोरी से अनुमान लगाने के बजाय लॉग या डेटाबेस से अधूरे कार्यों का पुनर्निर्माण करें।
चरण 6: विफलता, रद्दीकरण और पुनः प्रयासों को संभालें
खोए हुए वर्कर को पहले अज्ञात (unknown) के रूप में चिह्नित करें, फिर लीज और हार्टबीट विंडो के बाद पुनः प्राप्त करें। चेकपॉइंट से रिकवर करने योग्य जॉब्स को फिर से शुरू करें; गैर-इडेम्पोटेंट प्रभावों के लिए स्थिति लुकअप या मुआवजे की आवश्यकता होती है। रीट्राई कैप्ड बैकऑफ़ के साथ टेनेंट और जॉब बजट की खपत करते हैं। रिकवरी को सभी टाइम-आउट कार्यों को एक साथ पुनः डिस्पैच नहीं करना चाहिए।
चरण 7: क्षमता को स्केल करें और पॉलिसी बदलें
नोड्स या भार बदलने पर वर्ज़न वाली पॉलिसी प्रकाशित करें। पहले से कतारबद्ध कार्यों के लिए पुरानी पॉलिसी रखें और नए कार्य को धीरे-धीरे माइग्रेट करें; भार परिवर्तन से वादा किए गए शेयर को तुरंत रद्द नहीं किया जाना चाहिए। दुर्लभ GPU, ज़ोन और लोकल-डिस्क संसाधनों को अलग से ट्रैक करें, जिसमें उधारी और रिक्लेमेशन के लिए ऑडिट इवेंट्स शामिल हों।
चरण 8: निष्पक्षता और दक्षता को सत्यापित करें
सिंथेटिक और वास्तविक वर्कलोड्स के साथ लोड-टेस्ट करें: एक संतृप्त टेनेंट, कई धीमे टेनेंट, रैंडम नोड हानि, चेकपॉइंट रिकवरी और हॉट पॉलिसी परिवर्तन। टेनेंट प्रतीक्षा p50/p95, संसाधन शेयर, अधिकतम भुखमरी अंतराल, प्रीएम्प्शन, डुप्लिकेट निष्पादन, कतार आयु, विखंडन और रिकवरी समय को मापें। ट्रेड-ऑफ दिखाने के लिए FIFO, सख्त प्राथमिकता और निष्पक्ष शेड्यूलिंग की तुलना करें।
उच्च-गुणवत्ता वाला नमूना उत्तर
मैं कोटा, प्राथमिकता और नोड व्यवहार्यता को अलग रखूँगा। टेनेंट कतारों को भारित कम-सेवा प्राप्त कार्य और बाउंडेड एजिंग द्वारा चुना जाता है। उधारी समाप्त होने वाली निष्क्रिय क्षमता का उपयोग करती है; प्रीएम्प्शन के लिए रिकवरी प्रमाण, कोटा जांच और चेकपॉइंट बजट की आवश्यकता होती है। प्रत्येक असाइनमेंट एक आरक्षण, लीज और फेंसिंग टोकन को सुरक्षित रखता है, जबकि परिणाम प्रयास के आधार पर इडेम्पोटेंट होते हैं। शेड्यूलर अपने लॉग से पुनर्निर्माण करता है और रीट्राई टेनेंट बजट का उपभोग करते हैं। विफलता परीक्षण एक नॉइज़ी नेबर और वर्कर हानि उत्पन्न करते हैं, फिर टेनेंट प्रतीक्षा, शेयर, भुखमरी, डुप्लिकेट कार्य, विखंडन और रिकवरी समय की तुलना करते हैं।
सामान्य गलतियाँ
- एक वैश्विक प्राथमिकता कतार → एक बड़ा टेनेंट शीर्ष पर कब्जा कर लेता है → टेनेंट-लोकल जॉब से पहले एक टेनेंट चुनें।
- कोटा को प्राथमिकता मानना → जरूरी काम सीमाओं को बायपास कर देता है → कोटा जांच को परमाणु और स्वतंत्र रखें।
- असीमित प्रीएम्प्शन → चेकपॉइंट लागत और डुप्लिकेट प्रभाव अनियंत्रित हो जाते हैं → बजट और कूलडाउन जोड़ें।
- केवल-मेमोरी कतारें → पुनरारंभ होने पर डिस्पैच डुप्लिकेट हो जाता है या खो जाता है → आरक्षण, लीज और टोकन को बनाए रखें।
- केवल क्लस्टर औसत → एक टेनेंट अदृश्य रूप से भूखा रह सकता है → प्रतीक्षा और शेयर को टेनेंट द्वारा विभाजित करें।
- वर्कर हानि के बाद तत्काल रीट्राई → पुराना निष्पादन अभी भी चल सकता है → फेंसिंग की प्रतीक्षा करें या एक इडेम्पोटेंट पाथ का उपयोग करें।
फॉलो-अप प्रश्न
आप भुखमरी न होने को कैसे साबित करते हैं?
प्रत्येक चलने योग्य टेनेंट के लिए न्यूनतम सेवा शेयर आरक्षित करें और एजिंग को सीमित करें। निश्चित क्षमता और लगातार शेड्यूल करने योग्य कार्य के तहत, सत्यापित करें कि अधिकतम प्रतीक्षा पॉलिसी सीमा के भीतर रहती है।
प्रीएम्प्शन के बाद आप डुप्लिकेट बिलिंग से कैसे बचते हैं?
तार्किक जॉब या कमिट किए गए चरण का बिल बनाएं, प्रत्येक प्रयास का नहीं। बाहरी प्रभाव एक इडेम्पोटेंसी कुंजी और स्थिति लुकअप का उपयोग करते हैं।
क्या होगा यदि कोटा निष्क्रिय क्षमता के साथ संघर्ष करता है?
समाप्त होने वाली उधारी की अनुमति दें और पुनः प्राप्त करने योग्य क्षमता रिकॉर्ड करें। पहले नई उधारी रोकें, फिर पूरा होने की प्रतीक्षा करें या केवल रिकवर करने योग्य कार्य को प्रीएम्प्ट करें।
क्या शेड्यूलर को मजबूत निरंतरता (strong consistency) की आवश्यकता है?
आरक्षण, लीज और फेंसिंग के लिए लीनियरिज़ेबल सशर्त अपडेट की आवश्यकता होती है; डैशबोर्ड एसिंक्रोनस हो सकते हैं। एक पुराना कैश अंतिम GPU आवंटित नहीं करना चाहिए।
निष्पक्ष शेड्यूलिंग कब अनावश्यक है?
एकल टेनेंट, निश्चित बैच विंडो, या सख्त प्राथमिकता के लिए जहां भुखमरी स्वीकार्य है, एक साधारण प्राथमिकता कतार को सत्यापित करना आसान है।
रोलबैक किस कारण से शुरू होता है?
डुप्लिकेट निष्पादन, असफल रिकवरी, प्रतीक्षा सीमा का उल्लंघन, या बजट से बाहर टेनेंट शेयर नई पॉलिसी को रोक देता है। पुराने वर्ज़न को पुनर्स्थापित करें और रीप्ले के लिए आरक्षण लॉग बनाए रखें।