इस विषय को कई (3+) साक्षात्कारों के दौरान उठाया गया था जो मैंने पिछले महीने और डेढ़ से अधिक भिन्न भिन्न रूपों में पारित किए हैं, लेकिन एक बात के बारे में। ऐसा लगता है, जानी-मानी चीजें - लेकिन उन सभी उत्तरों और स्पष्टीकरणों को एकत्र किया जो मैंने दिए (और बाद में Google में कुछ पाया), मैंने उन्हें अपने Google ड्राइव में नहीं रखने का फैसला किया, लेकिन एक छोटी समीक्षा लिखने के लिए।यह जावा में छोटे और विशिष्ट एंटरप्राइज़ / वेब अनुप्रयोगों के बारे में था, जिनमें से कई (अच्छी तरह से, 10-100 हजार ग्राहकों के लिए, एक मिलियन विज़िट आदि) हैं। इसे प्रश्नों और उत्तरों के रूप में एक सामान्यीकृत संवाद होने दें।
प्रश्न: मान लीजिए कि आपके पास एक टमाटर (Apache Tomcat) पर तैनात एक एप्लिकेशन (सबसे आम - JSP, स्प्रिंग, उदाहरण के लिए हाइबरनेट) है और आप एक बार नोटिस करते हैं कि टमाटर का सर्वर औसतन 80% लोड है। क्या करें?
एक: हम समानांतर में अलग-अलग सर्वरों पर कई टमाटर डालेंगे। वे अभी भी एक ही सर्वर पर एक ही डेटाबेस का उपयोग करेंगे।
प्रश्न: लेकिन उपयोगकर्ता आपके कई सर्वरों तक कैसे पहुंचेगा?
एक: हम एक लोड-बैलेंसर का उपयोग करते हैं, उदाहरण के लिए, mod_proxy के साथ अपाचे (अपाचे httpd) टोमेट्स के सामने खड़े हो सकते हैं - यह हमारे सभी टोमेट्स के बीच आने वाले (प्रॉक्सी) अनुरोधों को वितरित करेगा।
प्रश्न: लेकिन यह पता चल सकता है कि उपयोगकर्ता एक टॉमकैट पर लॉग इन करता है, और अगला लोड-बैलेंसर अनुरोध दूसरे को भेजता है, जहां उपयोगकर्ता लॉग इन नहीं होता है!
ए: हम एक सत्र आयोजित करने के तरीके के बारे में बात कर रहे हैं। उदाहरण के लिए, हम चिपचिपा सत्र करते हैं (उदाहरण के लिए, जब लोड-बैलेंसर अनुरोध में एक कुकी जोड़ता है, जो यह संकेत देता है कि यह कौन सा टॉमकैट करता है - और इस कुकी के बाद के सभी अनुरोधों को उसी सर्वर पर भेजता है। इस प्रकार, प्रत्येक व्यक्तिगत उपयोगकर्ता केवल एक के साथ काम करेगा। सर्वर।
क्यू: और अगर यह विशेष सर्वर क्रैश?
A: उपयोगकर्ता सत्र खो गया है। इसलिए, कैश में सत्र भंडारण का उपयोग करना बेहतर है। बॉक्स से बाहर टॉमकैट जानता है कि उन्हें उदाहरण के लिए मेमचैड में कैसे संग्रहीत किया जाए। यही है, हम कॉन्फ़िगरेशन में लाइन जोड़ते हैं और एक अलग सर्वर पर मेमेकैच्ड चलाते हैं - अब उस पर सभी टोमेट्स स्टोर सेशन हैं, और यदि उपयोगकर्ता को किसी अन्य सर्वर से अगला अनुरोध मिला है, तो वह इस पर ध्यान नहीं देगा - सत्र वैसे भी काम करेगा।
प्रश्न: सत्र कैश के अन्य लाभ क्या हैं?
ए: उदाहरण के लिए, आप एप्लिकेशन के नए संस्करण को केवल कई टमाटरों में से किसी एक पर तैनात कर सकते हैं, इसलिए कहते हैं कि 25% उपयोगकर्ता नया लॉगिन पृष्ठ देखते हैं और हमारे पास इच्छा व्यक्त करने का समय है यदि वे इसे पसंद नहीं करते हैं, अर्थात्। वे अनैच्छिक रूप से बीटा परीक्षक के रूप में काम करते हैं :)
प्रश्न: लेकिन यदि एप्लिकेशन संस्करण डेटाबेस का अलग-अलग उपयोग करते हैं?
एक: हम दो पड़ोसी संस्करणों के बीच पिछड़े संगतता को बनाए रखने के लिए आधार परिवर्तन डिज़ाइन कर सकते हैं। यह मुश्किल नहीं है। उदाहरण के लिए, आपको नए संस्करण के साथ कॉलम जोड़ने की आवश्यकता है, लेकिन केवल अगले रिलीज़ पर अनावश्यक हटा दें।
प्रश्न: ठीक है, अब हमारा आधार एक अड़चन बन रहा है। उस पर बढ़ते भार का हम क्या करेंगे?
ए: सबसे पहले, यह आधार और टमाटर के बीच एक कैश बनाने के लिए उपयोगी है। पहले भी, हम शायद ORM स्तर पर कैश का उपयोग करते हैं (उदाहरण के लिए, हाइबरनेट में दूसरा कैश स्तर)। सामान्य बिंदु यह है कि सत्र के दौरान, उपयोगकर्ता सीमित डेटा का उपयोग करता है, इसलिए उन्हें कैश करना सुविधाजनक है।
प्रश्न: लेकिन फिर भी, मान लीजिए कि कैश हमें बचाता नहीं है। मैं आधार पर भार को कैसे कम कर सकता हूं?
एक: हम कई तरीके हैं। उदाहरण के लिए, आप डेटाबेस के एक हिस्से को (कुछ विशेष रूप से पंपिंग टेबल को) दूसरे डेटाबेस को एक अलग सर्वर पर आवंटित कर सकते हैं, शायद यहां तक कि NoSQL स्टोरेज या कुछ विशेष कैश में भी। बेशक, डिजाइनिंग के दौरान इस अलगाव को करना बेहतर है :)
प्रश्न: और क्या तरीके हैं? डेटाबेस स्तर पर समाधान क्या हैं?
ए: आप तेज का उपयोग कर सकते हैं - इस मामले में, तालिकाओं को कई सर्वरों में विभाजित किया जाता है और आवश्यक एक तक पहुंच होती है, उदाहरण के लिए, आईडी-शनिक के बारे में। कुछ मामलों में, आप तुरंत विभाजित कर सकते हैं, उदाहरण के लिए, लेनदेन, लेनदेन, इलेक्ट्रॉनिक दस्तावेज़, आदि। एक उपयोगकर्ता के बारे में चूंकि आमतौर पर उपयोगकर्ता अन्य लोगों के दस्तावेजों के साथ काम नहीं करता है - जिसका अर्थ है कि उसके सभी डेटा को आसानी से एक सर्वर पर संग्रहीत किया जा सकता है।
प्रश्न: इस दृष्टिकोण का नुकसान क्या है?
ए: बाद में ऐसी तालिकाओं के साथ काम करना अधिक कठिन हो जाएगा - कई सर्वरों पर पड़ी एक तालिका के साथ जुड़ें जाहिर है कम कुशल होंगे - अनुक्रमण, मानदंड द्वारा प्रश्न, आदि, अधिक जटिल हो जाते हैं। सामान्य तौर पर, डिजाइन ही काफी जटिल है।
प्रश्न: क्या आप कोई अन्य विकल्प जानते हैं?
ए: सबसे आसान तरीका प्रतिकृति को कॉन्फ़िगर करना है, उदाहरण के लिए, ताकि डेटाबेस में कई सर्वरों पर प्रतियां हों, जिनमें से एक का उपयोग लेखन के लिए किया जाता है, और बाकी पढ़ने के लिए। ये बाद वाले अपडेट के साथ अपनी सामग्री को जल्दी से सिंक्रनाइज़ करते हैं। यह पता चला है कि डेटाबेस में प्रश्नों की कुल संख्या अब कई मशीनों में वितरित की गई है। बेशक, लेखन से अधिक पढ़ने पर यह उपयोगी है।
प्रश्न: क्या आगे स्केलिंग पथ आप की पेशकश कर सकता है?
एक: उदाहरण के लिए, संदेश कतार। मान लें कि उपयोगकर्ता एक नया लेनदेन सहेजता है - लेकिन हम इसे स्वयं डेटाबेस में नहीं लिखते हैं। इसके बजाय, हम कतार (RabbitMQ कहते हैं) को एक संदेश भेजते हैं कि इस तरह के डेटा को बचाया जाना चाहिए। यह संदेश कई सर्वरों में से एक को प्रसंस्करण और डेटाबेस को सहेजने के लिए जारी किया जाएगा। ऐसे सर्वरों की संख्या बढ़ाना (जब वितरित / प्रतिकृति डेटाबेस या कैश का उपयोग करना) आम तौर पर बहुत आसान होता है। हालांकि, इस स्तर पर वास्तुकला को पहले से ही अधिक ध्यान और प्रतिबिंब की आवश्यकता है - शायद यह भी वह क्षण है जब आवेदन पूरे पुनर्लेखन के लायक है :)
प्रश्न: ठीक है, यह स्पष्ट है, चलो कुछ और के बारे में बात करते हैं ... (और यहां वे कचरा संग्रहकर्ताओं के बारे में शुरू कर सकते हैं, या उन्हें एक सरणी में द्विआधारी खोज लिखने के लिए कह सकते हैं - जूँ की जांच - लेकिन यह अब महत्वपूर्ण नहीं है)
साक्षात्कारों पर अपनी "टिप्पणियों" को साझा करने के बाद, मैं निश्चित रूप से परिवर्धन, सुधार आदि के बारे में खुश रहूंगा। जो मेरे और अन्य सहयोगियों के लिए उपयोगी हो सकता है :)