जानने लायक तीन विफलता अवधारणाएँ
स्वागत
वितरित प्रणालियाँ (distributed systems) पैटर्न में विफल होती हैं। एक बार जब आप पैटर्न सीख लेते हैं, तो हर पोस्टमॉर्टम एक रहस्य के बजाय एक पहचान अभ्यास बन जाता है।
उत्पादन विफलता विश्लेषण में जो महत्वपूर्ण है, उसका अधिकांश हिस्सा तीन अवधारणाओं में शामिल है:
एकल बिंदु विफलता (SPOF): एक घटक जिसकी विफलता एक बड़ी प्रणाली को गिरा देती है। अक्सर यह छिपा होता है: वह DNS सर्वर जिस पर सभी निर्भर हैं; वह प्रमाणपत्र (certificate) जिसके विरुद्ध सब कुछ नवीनीकृत होता है; या एकल डेटाबेस मास्टर।
कैस्केडिंग फेलियर (Cascading failure): एक घटक की विफलता दूसरे की को ट्रिगर करती है, जो तीसरे की को ट्रिगर करती है। एक धीमा डेटाबेस API तह में टाइमआउट का कारण बनता है, जिससे रीट्राई (retries) होते हैं, जो डेटाबेस पर और अधिक लोड डालते हैं, जिससे और अधिक टाइमआउट होते हैं। विस्फोट फैलता जाता है।
ब्लास्ट रेडियस (Blast radius): जब एक हिस्सा विफल होता है, तो सिस्टम का कितना हिस्सा बंद हो जाता है। आर्किटेक्चरल विकल्प रेडियस को सीमित (bound) या असीमित (unbound) करते हैं। SPOF का ब्लास्ट रेडियस असीमित होता है। बल्कहेडेड (bulkheaded) सेवा का रेडियस सीमित होता है।
इस पाठ के अंत तक आप:
- निरीक्षण द्वारा आर्किटेक्चर में SPOFs की पहचान करेंगे
- कैस्केडिंग फेलियर पैटर्नों को पहचानेंगे: थंडरिंग हर्ड (thundering herd), रीट्राई स्टॉर्म (retry storm), क्वॉ ऑफ डेथ (queue of death)
- एक वास्तविक टाइमलाइन पढ़ें और ट्रिगर को उस लैटेंट डिफेक्ट (latent defect) से अलग करें जिसे ट्रिगर ने सतह पर लाया
- दोषमुक्त (blameless) एक्शन आइटम लिखें जो लोगों के बजाय सिस्टम को लक्षित करते हैं, जिसमें रोकथाम / पहचान / रिकवरी शामिल हों
- ब्लास्ट-रेडियस बाउंडिंग टूल्स के रूप में बल्कहेड्स (bulkheads) और सर्किट ब्रेकर (circuit breakers) के बारे में तर्क करें
एकल बिंदु विफलता (Single Point of Failure) की पहचान करें
स्तरीय वास्तुकला का निरीक्षण
एक छोटी वेब वास्तुकला पर विचार करें:
- DNS: api.example.com -> एक DNS प्रदाता द्वारा होस्ट किया गया एकल नेमसर्वर IP 203.0.113.10
- CDN: api.example.com के सामने एकल CDN वेंडर
- इंग्रेस: लोड बैलेंसर के पीछे दो रिवर्स प्रॉक्सी मशीनें
- बैकएंड: दो उपलब्धता क्षेत्रों (प्रति क्षेत्र तीन) में छह API रिप्लिका
- डेटाबेस: एक प्राथमिक (primary) + एक रीड रिप्लिका, एक ही उपलब्धता क्षेत्र में
- कैश: Redis क्लस्टर, तीन नोड्स जो एक ही दो उपलब्धता क्षेत्रों (availability zones) में फैले हुए हैं
प्रश्न: कौन से घटक SPOFs (Single Points of Failure) हैं? संकेत: SPOFs हमेशा स्पष्ट 'एकल मशीन' प्रकार के नहीं होते हैं। एक उपलब्धता क्षेत्र में स्थित तीन मशीनों का क्लस्टर उस क्षेत्र की विफलता के लिए एक SPOF है।
तीन क्लासिक कैस्केड पैटर्न
फेलियर डिपेंडेंसीज़ के माध्यम से यात्रा करते हैं
पैटर्न 1: थंडरिंग हर्ड। एक साझा संसाधन (कैश, लॉक, डेटाबेस) विफल हो जाता है या पुनः आरंभ (restart) होता है। हर वह क्लाइंट जो इस पर निर्भर था, एक ही समय पर पुनः प्रयास (retry) करता है। यह बाढ़ (flood) उस चीज़ को दबा देती है जो वापस आती है; पुनः प्रयास (retries) रिकवरी की क्षमता से तेजी से जमा होते हैं; रिकवरी कभी पूरी नहीं होती।
पैटर्न 2: रीट्री स्टॉर्म। एक डाउनस्ट्रीम सेवा धीमी हो जाती है। अपस्ट्रीम कॉलर्स, विफल होने के बजाय, पुनः प्रयास (retry) करते हैं। पुनः प्रयास (retries) मूल लोड को गुणा (multiply) करते हैं। धीमी सेवा और भी धीमी हो जाती है, जिससे और पुनः प्रयास (retries) ट्रिगर होते हैं। अंततः, लोड सेवा के एक स्वस्थ संस्करण (healthy version) की क्षमता से भी अधिक हो जाता है।
पैटर्न 3: क्वी ऑफ डेथ। एक प्रोसेसिंग क्यू (processing queue) जिसमें बैकप्रेशर (backpressure) नहीं है, उससे तेजी से इनपुट प्राप्त करता है जितनी तेजी से वह प्रोसेस करता है। क्यू (queue) असीमित रूप से बढ़ता है। मेमोरी खत्म हो जाती है; कन्ज्यूमर क्रैश (crash) हो जाता है; पुनः आरंभ (restart) होता है; एक और बड़ा क्यू (queue) पाता है; फिर से क्रैश (crash) हो जाता है।
सामान्य धागा: एक छोटी प्रारंभिक विचलन (perturbation) एक पॉज़िटिव-फीडबैक लूप (positive-feedback loop) को ट्रिगर करती है। सिस्टम का अपना प्रतिक्रिया विफलता को कम करने के बजाय उसे बढ़ाती है।
डैम्पिंग मीकनिज्म्स
जिटर के साथ एक्सपोनेंशियल बैकऑफ। जो क्लाइंट्स रीट्राई करते हैं, वे हर बार लंबे समय तक प्रतीक्षा करते हैं, जिसमें एक यादृच्छिक (random) ऑफसेट होता है। इससे सिंक्रोनाइज़्ड रीट्राई वेव्स (समय पर मिलकर होने वाले पुनर्प्रयास) को रोका जाता है।
सर्किट ब्रेकर। एक कॉलर (caller) डाउनस्ट्रीम (downstream) विफलता दर को ट्रैक करता है। एक सीमा (threshold) के पार जाने पर, कॉलर एक कूलडाउन अवधि के लिए कॉल करना बंद कर देता है और तुरंत अपने अपने अनुरोधों को विफल (fail) कर देता है। इससे बेकार की मेहनत बचती है और डाउनस्ट्रीम को रिकवरी (recover) करने का मौका मिलता है।
बल्कहेड। हर निर्भरता (dependency) के लिए संसाधनों को अलग करें। डेटाबेस के लिए कनेक्शन पूल A, और कैश के लिए अलग कनेक्शन पूल B। एक धीमा डेटाबेस सभी कनेक्शन को भूखा (starve) नहीं रख सकता; कैश कॉल जारी रहती हैं।
लोड शेडिंग। जब सिस्टम ओवरलोडेड हो, तो अनुरोधों को धीरे-धीरे विफल होने के बजाय एज (edge) पर ही छोड़ दें। 1 मिलीसेकंड में 429 (Too Many Requests) का कोड, 30 सेकंड में 500 (Internal Server Error) से बेहतर है।
बैकप्रेसर। जब कन्ज्यूमर (consumers) पीछे न रह जाएं, तो प्रोड्यूसर (producers) को धीमा करें। क्यू (queues) सीमित (bounded) हो जाती हैं; सेंडर ब्लॉक हो जाते हैं; और काम का मूल स्रोत उस घर्षण (friction) को महसूस करता है।
कैस्केड का निदान करें
एक टीम की API टियर रूटीन डेटाबेस फेलओवर के दौरान टूट जाती है। टाइमलाइन:
- 14:00:00 — ऑपरेटर स्टैंडबाय डेटाबेस को प्रमोट करता है। अपेक्षित अनुपलब्धता: ~10 सेकंड।
- 14:00:08 — प्राइमरी अनुपलब्ध। API टियर अनुरोध डेटाबेस कनेक्शन त्रुटियों के साथ विफल होने लगते हैं।
- 14:00:08 — API टियर पुनः प्रयास करता है (डिफ़ॉल्ट कॉन्फ़िग: 5 पुनः प्रयास, कोई बैकऑफ नहीं, 100ms अंतर)।
- 14:00:11 — स्टैंडबाय को प्रमोट किया गया, नए कनेक्शन स्वीकार किए जा रहे हैं।
- 14:00:11 — API टियर एक साथ हज़ारों नए डेटाबेस कनेक्शन खोलता है (हर रिप्लिका × हर समानांतर अनुरोध × हर पुनः प्रयास)।
- 14:00:13 — नए प्राइमरी का कनेक्शन पूल खाली हो गया; नए कनेक्शन अस्वीकृत किए गए।
- 14:00:13-14:05:00 — API टियर रिप्लिका कनेक्शन पूल खाली कर देते हैं, अपवाद (exceptions) फेंकते हैं, क्रैश करते हैं, पुनः आरंभ होते हैं, और यह चक्र दोहराया जाता है।
- 14:05:00 — ऑपरेटर ने API टियर ट्रैफ़िक को मैन्युअल रूप से रोक दिया; डेटाबेस स्थिर हो गया।
- 14:10:00 — क्रमिक ट्रैफिक पुनर्स्थापना पूर्ण। कुल आउटेज: ~10 मिनट (अपेक्षित ~10 सेकंड के विपरीत)।
DNS SERVFAIL: दो एक-दूसरे को बढ़ावा देने वाले दोष
एक वास्तविक-आकार का पोस्टमॉर्टम
नीचे दी गई जानकारी एक वास्तविक घटना का सैनिटाइज़्ड (संस्करण) है। वेंडर के नाम बदले गए हैं, IP एनानाइमाइज़ किए गए हैं; लेकिन आकार, टाइमलाइन और पाठ वास्तविक हैं।
सारांश
साइट example.com लगभग 3-4 घंटों तक सभी सार्वजनिक DNS रिज़ॉल्वर्स से SERVFAIL लौटा रही थी। उसी DNS मास्टर पर मौजूद अन्य सभी 46 ज़ोन प्रभावित नहीं हुए थे। मूल कारण: दो एक-दूसरे को बढ़ावा देने वाले दोष।
1. वेंडर A (एक सेकेंडरी DNS प्रदाता) ने एक नया आंतरिक सिंक IP जोड़ा था जो प्राथमिक के allow-axfr-ips अलाउ-लिस्ट में शामिल नहीं था।
2. example.com ज़ोन में एक वर्षों पुरानी RFC-उल्लंघन करने वाली CNAME टकराव थी (demo.example.com के पास एक ही लेबल पर CNAME और MX/TXT रिकॉर्ड दोनों मौजूद थे), जिसके कारण वेंडर A ने नए AXFR पर ज़ोन को अस्वीकार कर दिया।
टाइमलाइन (UTC)
- ~15:00 — Vendor A ने अपनी इंफ्रास्ट्रक्चर में नया सिंक IP 198.51.100.42 जोड़ा
- 15:02 — प्राथमिक DNS लॉग्स में 198.51.100.42 के लिए पहली बार AXFR-out denied दिखाई दिया (इस संकेत पर कोई अलर्टिंग नहीं थी)
- ~18:00 — SOA expire window पूरा हुआ; Vendor A ने example.com ज़ोन को कैश से हटा दिया
- ~18:30 — बाहर से SERVFAIL का पता चला
- ~19:45 — मूल कारण (root cause) की पहचान की गई
- 20:00 — 198.51.100.42 को allow-axfr-ips में जोड़ा गया; प्राथमिक (primary) को पुनः आरंभ किया गया
- 20:05 — NOTIFY भेजा गया; AXFR प्रारंभ किया गया; ज़ोन अभी भी SERVFAIL में है (CNAME टकराव)
- 20:07 — check-zone से 1 त्रुटि का पता चला: demo.example.com पर CNAME टकराव
- 20:09 — CNAME को A record से बदला गया; ज़ोन जाँच साफ़ (0 त्रुटियाँ)
- 20:10 — NOTIFY भेजा गया; AXFR पूरा हुआ; Vendor A ज़ोन सर्व करने लग गया
- 20:11 — dig @8.8.8.8 example.com A सही IP लौटाता है — RESOLVED
केवल example.com क्यों?
सभी 47 ज़ोन एक ही DNS प्राथमिक (primary) साझा करते हैं। AXFR IP ब्लॉक ने सभी ज़ोन को प्रभावित किया। लेकिन केवल example.com में CNAME टकराव था, & केवल example.com को उस समय ताज़ा AXFR की आवश्यकता थी जब अस्वीकृति (deny) लागू की गई थी। अन्य ज़ोन पहले से ही अस्वीकृति से पहले ताज़ा हो चुके थे या उन्हें अभी आवश्यकता नहीं थी।
गुप्त दोष (Latent defect)
demo.example.com पर CNAME टकराव वर्षों से मौजूद था। यह इसलिए काम कर रहा था क्योंकि प्राथमिक (primary) ने ज़ोन को उसके डेटाबेस से सर्व किया (RFC उल्लंघनों के प्रति सहिष्णु) & Vendor A पुराने कैश्ड डेटा से सर्व कर रहा था जो उल्लंघन प्रस्तुत होने से पहले का था। जब Vendor A ने अपना कैश ड्रॉप किया & ताज़ा डेटा की आवश्यकता हुई, तो उल्लंघन सतह पर आया।
ट्रिगर
वेंडर A ने चुपचाप एक नया सिंक IP जोड़ा। प्राथमिक (primary) की अलाउलिस्ट (allowlist) में यह शामिल नहीं था। AXFR अस्वीकार कर दिया गया। तीन घंटे बाद (SOA expire), वेंडर A ने ज़ोन ड्रॉप कर दिया। जब सिस्टम रिकवरी करने की कोशिश करने लगा, तब छिपा हुआ दोष (latent defect) सतह पर आया।
ब्लेमलेस एक्शन आइटम लिखें
ब्लेमलेस: लोगों को नहीं, सिस्टम को निशाना बनाएं
ब्लेमलेस एक्शन आइटम किसी ऐसी चीज़ का नाम लेता है जो सिस्टम को अलग ढंग से करना चाहिए, न कि किसी व्यक्ति को अलग ढंग से करना चाहिए। 'ऑपरेटर को प्रशिक्षित करें' यह ब्लेमफुल (blameful) है। 'एक स्वतः-संचालित जांच जोड़ें जो डिप्लॉय से पहले इसे पकड़ ले' यह ब्लेमलेस है।
अच्छे ब्लेमलेस एक्शन आइटम तीन आयामों में समूह बनाते हैं:
- प्रीवेंशन (Prevention): बुरी चीज़ को कठिन या असंभव बनाएं
- डिटेक्शन (Detection): यदि यह होता है, तो इसे जल्दी से पहचानें
- रिकवरी (Recovery): यदि यह होता है, तो नुकसान को सीमित करें
प्रत्येक आइटम को (1) विशिष्ट सिस्टम परिवर्तन, (2) एक मालिक टीम, और (3) उस आयाम का नाम देना चाहिए जिसकी यह सेवा करता है।
वे कक्ष जो जहाज़ के साथ नहीं डूबते
नौवहन इंजीनियरिंग से उधार लिया गया
जहाज़ों में जलरोधक बल्कहेड्स (watertight bulkheads) होते हैं: ऊर्ध्वाधर दीवारें जो हल (hull) को कक्षों में विभाजित करती हैं। एक कक्ष में पानी भर सकता है बिना जहाज़ को डुबोए; एक और कक्ष विफल हो सकता है बिना बाकी के हिस्सों को प्रभावित किए।
वितरित प्रणालियाँ (distributed systems) उसी शब्द और उसी विचार को उधार लेती हैं।
बल्कहेड पैटर्न: प्रति निर्भरता (dependency) के अनुसार संसाधनों को अलग करें। एक सेवा जो तीन डाउनस्ट्रीम API को कॉल करती है, वह तीन अलग कनेक्शन पूल्स, तीन अलग थ्रेड पूल्स और तीन अलग रीट्राई बजट्स का उपयोग करती है। एक धीमा या विफल डाउनस्ट्रीम अन्य दो के लिए आवंटित संसाधनों को खपत नहीं कर सकता।
बल्कहेड्स के बिना: एक धीमा निर्भरता (dependency) साझा थ्रेड पूल को खत्म कर देती है; अन्य निर्भरताओं पर कॉल थ्रेड्स के लिए प्रतीक्षा करते हुए ब्लॉक हो जाती हैं; पूरी सेवा प्रतिक्रियाशील (unresponsive) हो जाती है।
बल्कहेड्स के साथ: एक धीमा निर्भरता (dependency) अपना पूरा पूल खत्म कर देती है; उस पर कॉल तेजी से विफल हो जाती हैं; अन्य निर्भरताओं पर कॉल सामान्य रूप से जारी रहती हैं; विफलता का प्रभाव (blast radius) विफल निर्भरता तक सीमित रहता है।
सर्किट ब्रेकर
सर्किट ब्रेकर पैटर्न: एक स्टेटफुल (stateful) रैपर जो डाउनस्ट्रीम निर्भरता (downstream dependency) के चारों ओर होता है और विफलता दर (failure rate) को ट्रैक करता है। तीन अवस्थाएँ:
- बंद (सामान्य): कॉल पास हो जाते हैं। विफलताओं की गिनती की जाती है।
- खुला (ट्रिप हो गया): विफलता सीमा (failure threshold) के पार जाने पर (उदाहरण के लिए, पिछले 30 सेकंड में 50% विफलता), ब्रेकर खुल जाता है। कॉल तुरंत विफल हो जाते हैं, बिना निर्भरता (dependency) को आज़माए। यह कॉलर (caller) को बेकार काम करने से बचाता है; और निर्भरता (dependency) को अस्वस्थ अवस्था में लोड प्राप्त करने से बचाता है।
- आधा-खुला (परीक्षण): एक कूलडाउन अवधि के बाद, ब्रेकर कॉलों का एक छोटा सा अंश पास होने देता है। यदि वे सफल होते हैं, तो यह सामान्य अवस्था में वापस बंद हो जाता है। यदि वे विफल होते हैं, तो यह एक और कूलडाउन के लिए फिर से खुल जाता है।
मुख्य अंतर्दृष्टि: सर्किट ब्रेकर ज्ञात-अस्वस्थ अवधि के दौरान बेकार प्रयासों को रोकता है, और डाउनस्ट्रीम को निरंतर लोड के बिना रिकवरी का मौका देता है।
बल्कहेड्स (Bulkheads) ब्लास्ट रेडियस (विस्फोट की सीमा) को सीमित करते हैं। सर्किट ब्रेकर ब्लास्ट को स्वयं को बनाए रखने से रोकते हैं।
ब्लास्ट रेडियस को सीमित करें
आपका API सेवा चार डाउनस्ट्रीम सेवाओं को कॉल करता है: यूज़र सेवा, रिकमेंडेशन सेवा, नोटिफिकेशन सेवा, और एक थर्ड-पार्टी पेमेंट API। टीम को यह सुना है कि 'रिकमेंडेशन सेवा थोड़ी फ्लैकी (अस्थिर) रही है' और वे यह सुनिश्चित करना चाहते हैं कि जब यह विफल हो, तो सिस्टम का बाकी हिस्सा स्वस्थ रहे।
आज सेवा एक साझा थ्रेड पूल (200 थ्रेड) और एक साझा HTTP कनेक्शन पूल का उपयोग करती है। चारों डाउनस्ट्रीम इन संसाधनों के लिए प्रतिस्पर्धा करते हैं। कोई सर्किट ब्रेकर नहीं है।
एक फेल्यर-मोड रिव्यू डिज़ाइन करें
संश्लेषण
आपने सीखा है कि निरीक्षण द्वारा SPOFs (Single Points of Failure) को पहचानना, कैस्केडिंग फेल्यर पैटर्न को पहचानना, पोस्टमॉर्टम पढ़ते समय ट्रिगर और लैटेंट डिफेक्ट (गुप्त दोष) को अलग करना, रोकथाम / पहचान / रिकवरी के लिए ब्लेमलेस (दोष-मुक्त) एक्शन आइटम लिखना, और बल्कहेड + सर्किट ब्रेकर + ग्रेसफुल डिग्रेडेशन के साथ ब्लास्ट रेडियस को सीमित करना।
पাঁचों का प्रयोग करें।
आपकी टीम एक नया सर्विस search.example.com लॉन्च कर रही है, जो तीन डाउनस्ट्रीम सर्विसेज पर निर्भर है: एक प्राथमिक सर्च इंडेक्स (index.example.com), एक एनालिटिक्स सर्विस (analytics.example.com), और एक रिकमेंडेशन सर्विस (recs.example.com)। टीम चाहती है कि आप लॉन्च से पहले 'फेल्यर-मोड रिव्यू' की अगुवाई करें।
यह कोर्स आगे कहाँ जाता है
यह कोर्स आगे कहाँ जाता है
आप अब SPOF को पहचान सकते हैं, एक कैस्केड को पहचान सकते हैं, एक पोस्टमॉर्टम को उत्पादकता से पढ़ सकते हैं, दोषमुक्त एक्शन आइटम लिख सकते हैं, और डिज़ाइन के माध्यम से ब्लैस्ट रेडियस को सीमित कर सकते हैं।
इस कोर्स का अंतिम पाठ (cs_distsys_observability_and_capacity) सिखाता है कि आपको क्या मापना चाहिए ताकि आप उपयोगकर्ताओं को पता चलने से पहले ही यह जान सकें कि कोई समस्या हो रही है। हेल्थ चेक्स, वर्जन एंडपॉइंट्स, एक प्रॉक्सी टियर पर चार गोल्डन सिग्नल, और यह कि सर्ज कैपैसिटी निर्णय कैसे अवलोकित डेटा से वापस जुड़ते हैं।
सहपाठ: geometry_of_failure_modes_and_blast_radius बीचता केंद्रता (कौन सा ग्राफ़ नोड बोतल गला है) और मिन-कट (ब्लैस्ट रेडियस की सीमा) व्युत्पन्न करता है।
बहुत बढ़िया। आगे बढ़ें।