प्रत्येक सर्व्हरसाठी नव्हे, एकदाच वाजणारे अलर्ट
आमचा एक ऑपरेशनल अलर्ट, “low credits”, जो बिल्डरच्या प्रकाशित ॲपसाठी असतो, तो जास्तीत जास्त दिवसातून एकदाच आमच्यापर्यंत पोहोचायला हवा होता. एका दुपारी तो पाच वेळा आला. कारण: आमच्या API च्या प्रत्येक प्रतीने, कोणते अलर्ट आधीच पाठवले आहेत ते स्वतःच्या मेमरीत लक्षात ठेवले होते, त्यामुळे दोन सर्व्हर्सनी तो दोनदा पाठवला, आणि प्रत्येक डिप्लॉयने ती मेमरी पुसून त्यांना पुन्हा पाठवायला मोकळे केले. त्याच पद्धतीमुळे एक बॅकग्राउंड जॉबही त्याचे काम दुप्पट करत होता. आता दोन्ही एका शेअर्ड स्टोअरद्वारे समन्वय साधतात, आणि ते स्टोअर उपलब्ध नसेल तर दोन्ही सुरक्षित बाजूने अपयशी ठरतात.
लक्षण
Mythex काही लक्ष देण्याची गरज असेल तेव्हा टीमला अलर्ट पाठवते: सर्व्हिस बंद पडली, जॉब अडकला, किंवा बिल्डरच्या प्रकाशित ॲपची क्रेडिट शिल्लक कमी होत आहे. प्रत्येक अलर्टला एक डिडुप्लिकेशन विंडो असते, म्हणजे एका कालावधीत तोच अलर्ट फक्त एकदाच पाठवला जातो. कमी क्रेडिट्सच्या अलर्टसाठी ती विंडो 24 तास आहे.
एका दुपारी एकाच अलर्टच्या पाच प्रती आल्या म्हणजे विंडो टिकत नव्हती. त्याहूनही वाईट म्हणजे त्या जोड्यांमध्ये, साधारण 11 मिनिटांच्या अंतराने येत होत्या.
हे का झाले
आमच्या अलर्ट पॅकेजमध्ये डिडुप्लिकेशन मेमरीमध्ये ठेवलेले होते: “अलर्ट की → शेवटचा कधी पाठवला” असे एक टेबल, चालू प्रक्रियेच्या आत. एकच प्रक्रिया जी कधीच रीस्टार्ट होत नाही, तिथे हे चालते. प्रॉडक्शनमध्ये मात्र दोन्ही गोष्टी नसतात:
- दोन API रेप्लिका. प्रॉडक्शनमध्ये API च्या दोन प्रती चालतात. प्रत्येकाचे स्वतःचे टेबल होते, त्यामुळे प्रत्येकाने अलर्ट एकदा पाठवला. हीच जोडी.
- डिप्लॉय. प्रत्येक डिप्लॉय दोन्ही रेप्लिकांना रिकाम्या टेबलांसह नवीन प्रक्रियांनी बदलतो. डिप्लॉयनंतर अलर्ट पुन्हा गेला, जणू कधी पाठवलाच नव्हता.
प्रत्येक जोडीतील दोन अलर्टमधील ~11 मिनिटांचे अंतर त्या अलर्टला उभा करणाऱ्या जॉबमधून आले. तो दोन्ही रेप्लिकांवर चालतो आणि एक लॉक घेतो, त्यामुळे रेप्लिका आळीपाळीने ते लॉक जिंकतात, आणि प्रत्येक जण आपली पाळी आली की अलर्ट उभा करत होता.
त्याच कोडमध्ये आणखी एक शांत बग होता. टेबल कायमचे वाढू नये म्हणून, त्यात 500 की झाल्यावर ते स्वतःची छाटणी करत असे: प्रत्येक जुनी एन्ट्री, तिची विंडो काहीही असली तरी, 15 मिनिटांनी जुनी असेल तर हटवत असे. भारानुसार, 24 तासांची डिडुप्लिकेशन विंडो एक चतुर्थांश तासच टिकत होती.
उपाय
प्रत्येक अलर्टसाठी एक शेअर्ड रेकॉर्ड
आता API अलर्ट पाठवण्यापूर्वी, त्या अलर्टची डिडुप्लिकेशन की Redis मध्ये दावा करते. Redis हा एक शेअर्ड इन-मेमरी स्टोअर आहे, ज्याच्याशी दोन्ही रेप्लिका बोलतात, आणि API रीस्टार्ट झाला तरी जो रीस्टार्ट होत नाही. हा दावा एकच ऑपरेशन आहे: “ही की फक्त तेव्हाच सेट करा जेव्हा ती अस्तित्वात नसेल, आणि विंडोनंतर ती कालबाह्य होऊ द्या.” जी रेप्लिका प्रथम दावा करते ती अलर्ट पाठवते; दुसरी की आधीच घेतलेली पाहून शांत राहते. डिप्लॉयनंतरची नवीन प्रक्रिया अजूनही ती की तिथे असल्याचे पाहते.
की आणि विंडो अलर्ट पॅकेज वापरत असलेल्या त्याच नियमातून येतात, आता त्या दोघांमध्ये शेअर्ड, त्यामुळे “तोच अलर्ट” म्हणजे काय यावर दोन थर कधीही वेगळे मत ठेवू शकत नाहीत.
अपयश उघड्या बाजूला, बंद बाजूला नाही
सर्वात महत्त्वाचा निर्णय होता की Redis पोहोचू शकत नसेल तर काय करायचे. आम्ही अलर्ट तरीही पाठवायचे ठरवले. Redis बंद असेल, किंवा 1.5 सेकंदांत उत्तर देत नसेल, तर अलर्ट जातो. डुप्लिकेट अलर्ट हा गोंधळ आहे. गाळलेला अलर्ट म्हणजे कोणाला सांगितले न जाणे.
सर्वात गंभीर अलर्ट, P0, डिडुप्लिकेशनमुळे अजिबात थांबवले जात नाहीत.
प्रत्येक एन्ट्रीची स्वतःची विंडो
अलर्ट पॅकेजच्या स्वतःच्या मेमरीतील डिडुप्लिकेशनमध्ये, आता प्रत्येक एन्ट्री तिची विंडो कधी संपते ते साठवते, आणि छाटणी फक्त ज्या एन्ट्रींची विंडो संपली आहे त्या काढते. 24 तासांची की 24 तास टिकते, इतर किती अलर्ट आले तरी.
त्याच बगचा दुसरीकडे प्रकार
त्याच पद्धतीमुळे एक बॅकग्राउंड काम देखील दुप्पट होत होते: एक रीकन्सिलिएशन जॉब जो प्रत्येक वर्कस्पेसची स्थिती आमच्या सँडबॉक्स प्रदात्याच्या स्थितीशी जुळवून ठेवतो. प्रत्येक पासमध्ये खात्यातील प्रत्येक सँडबॉक्स यादी केला जातो (प्रॉडक्शनमध्ये हजारो, सुमारे पाच सेकंद), तसेच प्रत्येक चालू किंवा थांबवलेला प्रोजेक्ट. दोन्ही रेप्लिका हा जॉब दर दोन मिनिटांनी चालवत होत्या.
त्याचे लेखन idempotent होते, म्हणजे ते दोनदा चालवले तरी निकाल एकदा चालवल्यासारखाच येतो, त्यामुळे काहीही तुटले नाही. फक्त काम दुप्पट होत होते. आता प्रत्येक दोन मिनिटांची विंडो Redis मध्ये त्याच पद्धतीने दावा केली जाते, जसे आमचे वापर मीटर त्यांचे दावे करतात, आणि तो दावा करणारी रेप्लिकाच पास चालवते. Redis पोहोचू शकत नसेल तरी पास चालतो: काम दोनदा होणे निरुपद्रवी आहे, न होणे नाही.
आम्ही ते कसे तपासले
चाचण्या खऱ्या सेटअपचे मॉडेल करतात. त्या अलर्ट मॉड्यूल दोनदा लोड करतात, “दोन स्वतंत्र रेप्लिका” म्हणून, दोघांना एका शेअर्ड स्टोअरकडे निर्देशित करतात, प्रत्येकातून तोच अलर्ट उभा करतात, मग “डिप्लॉयनंतर” ची जागा घेण्यासाठी तिसरी नवी प्रत लोड करतात आणि तो पुन्हा उभा करतात. नेमका एक अलर्ट पाठवला जातो. इतर चाचण्या तपासतात की वेगळ्या बिल्डरचा अलर्ट अजूनही जातो, P0 दोन्ही रेप्लिकांमधून पाठवला जातो, आणि स्टोअर बंद असताना किंवा टाइमआउटच्या पलीकडे अडकलेले असतानाही अलर्ट जातो. छाटणी दुरुस्तीची स्वतःची चाचणी आहे: 24 तासांची की 20 मिनिटांनंतर आलेल्या 600 इतर अलर्टनंतरही टिकते.
रीकन्सिलिएशन जॉबसाठी, एकाच विंडोमध्ये दोन रेप्लिका एकाच वेळी टिक करतात, आणि त्यात तिसरा टिक, एक लिस्टिंग तयार करतात.
आम्ही यातून काय शिकलो
- इन-मेमरी स्थिती प्रति प्रक्रिया असते. सर्व्हर्सच्या पलीकडे जे खरे असले पाहिजे, जसे “एकदाच पाठवला” किंवा “एकदाच चालला”, ते त्यांनी शेअर करावयाच्या ठिकाणी असले पाहिजे.
- डिप्लॉय म्हणजे रीस्टार्ट. पुढच्या रीस्टार्टपर्यंत टिकणारी स्थिती सामान्य कामाच्या दिवसातही टिकत नाही.
- कोणत्या दिशेने अपयशी ठरायचे ते ठरवा. अलर्टसाठी, शेअर्ड स्टोअर बंद असणे म्हणजे कमी नव्हे तर जास्त अलर्ट यायला हवेत.
- फक्त उदाहरण नव्हे, नमुना शोधा. अलर्ट हा मोठा, दिसणारा प्रकार होता; दुप्पट होणारा रीकन्सिलिएशन जॉब तोच बग होता, जो शांतपणे काम वाया घालवत होता.
हे Mythex आतून दिसत नाही. प्लॅटफॉर्म स्थिर कसा ठेवतो याबद्दल अधिक माहितीसाठी, डिप्लॉयमध्ये 502 एरर शून्यावर कशा आणल्या आणि गहाळ स्वॅप फाइल पाहा. एकाच सेवेच्या एकापेक्षा जास्त प्रती चालवण्याच्या कल्पनेसाठी नवीन असाल, तर सर्व्हर म्हणजे काय हे मार्गदर्शक मूलभूत गोष्टी सांगते.