कनेक्शन-सीमा विवश डेटाबेस के लिए उच्च आवृत्ति घटनाओं को सहेजना


13

हमें एक ऐसी स्थिति मिली है जहां मुझे अपने सर्वर पर आने वाली घटनाओं के एक बड़े प्रवाह से निपटना होगा, औसतन प्रति सेकंड लगभग 1000 घटनाएं (शिखर ~ 2000 हो सकती हैं)।

समस्या

हमारा सिस्टम हेरोकू पर होस्ट किया गया है और अपेक्षाकृत महंगे हरोकू पोस्टग्रब्स डीबी का उपयोग करता है , जो अधिकतम 500 डीबी कनेक्शन की अनुमति देता है। हम सर्वर से डीबी से कनेक्ट करने के लिए कनेक्शन पूलिंग का उपयोग करते हैं।

डीबी कनेक्शन पूल की तुलना में ईवेंट तेजी से आ सकते हैं

हमारे पास समस्या यह है कि कनेक्शन पूल को संभालने की तुलना में घटनाएं तेजी से आती हैं। जब तक एक कनेक्शन सर्वर से DB तक नेटवर्क राउंडट्रिप को पूरा कर लेता है, तब तक यह पूल में वापस आ सकता है, nअतिरिक्त ईवेंट अधिक से अधिक आते हैं।

अंततः ईवेंट्स ढेर हो जाते हैं, सहेजने के लिए प्रतीक्षा करते हैं और क्योंकि पूल में कोई उपलब्ध कनेक्शन नहीं हैं, वे समय से बाहर हो जाते हैं और पूरी प्रणाली को गैर-परिचालन प्रदान किया जाता है।

हमने ग्राहकों से धीमी गति से आक्रामक उच्च आवृत्ति वाली घटनाओं का उत्सर्जन करके आपातकाल को हल कर दिया है, लेकिन हम अभी भी जानना चाहते हैं कि उस घटना को कैसे संभालना है जो हमें उस उच्च आवृत्ति घटनाओं को संभालने की आवश्यकता है।

प्रतिबन्ध

अन्य ग्राहक समवर्ती घटनाओं को पढ़ना चाहते हैं

अन्य ग्राहक किसी विशेष कुंजी के साथ सभी घटनाओं को पढ़ने के लिए लगातार अनुरोध करते हैं, भले ही वे अभी तक डीबी में सहेजे नहीं गए हों।

एक क्लाइंट GET api/v1/events?clientId=1क्लाइंट 1 द्वारा भेजे गए सभी ईवेंट को क्वेरी और प्राप्त कर सकता है , भले ही उन घटनाओं को डीबी में अभी तक बचत नहीं की गई हो।

क्या इससे निपटने के लिए कोई "कक्षा" उदाहरण हैं?

संभव समाधान

हमारे सर्वर पर घटनाओं को दर्ज करें

हम सर्वर पर होने वाली घटनाओं को समझ सकते हैं (कतार में 400 की अधिकतम समवर्ती होने के कारण कनेक्शन पूल नहीं चलता है)।

यह बुरा विचार है क्योंकि:

  • यह उपलब्ध सर्वर मेमोरी को खा जाएगा। स्टैक्ड-अप एन्केड की गई घटनाओं से भारी मात्रा में रैम की खपत होगी।
  • हमारे सर्वर हर 24 घंटे में एक बार पुनः आरंभ करते हैं । यह हरोकू द्वारा लगाई गई एक कठिन सीमा है । सर्वर पुनः आरंभ कर सकता है जबकि घटनाओं की गणना की जा रही है, जिससे हमें संलग्न घटनाओं को खोना पड़ता है।
  • यह सर्वर पर स्थिति का परिचय देता है, इस प्रकार स्केलेबिलिटी को नुकसान पहुंचाता है। यदि हमारे पास एक मल्टी-सर्वर सेटअप है और एक क्लाइंट सभी एन्केस्ड + सेव किए गए इवेंट्स को पढ़ना चाहता है, तो हमें यह पता नहीं चलेगा कि किस सर्वर पर एनक्वाइडेड इवेंट्स रहते हैं।

एक अलग संदेश कतार का उपयोग करें

मुझे लगता है कि हम एक संदेश कतार का उपयोग कर सकते हैं, (जैसे RabbitMQ ?), जहां हम इसमें संदेशों को पंप करते हैं और दूसरे छोर पर एक और सर्वर होता है जो केवल डीबी पर घटनाओं को सहेजने से संबंधित है।

मुझे यकीन नहीं है कि यदि संदेश कतारों की गणना की घटनाओं की अनुमति देता है (जो अभी तक सहेजे नहीं गए थे) तो यदि कोई अन्य ग्राहक किसी अन्य क्लाइंट के संदेशों को पढ़ना चाहता है, तो मैं केवल सहेजे गए संदेशों को डीबी और कतार से लंबित संदेशों को प्राप्त कर सकता हूं। और उन्हें एक साथ समेटना ताकि मैं उन्हें रीड-रिक्वेस्ट क्लाइंट को वापस भेज सकूं।

उन्हें प्रबंधित करने के लिए केंद्रीय डीबी-समन्वयक सर्वर के साथ संदेशों के एक हिस्से को सहेजने वाले कई डेटाबेस का उपयोग करें

एक और समाधान जो हमने हालांकि कई डेटाबेस का उपयोग करना है, एक केंद्रीय "डीबी समन्वयक / लोड बैलेंसर" के साथ है। एक ईवेंट प्राप्त करने पर यह समन्वयक संदेश को लिखने के लिए डेटाबेस में से एक का चयन करेगा। यह हमें कई हेरोकू डेटाबेस का उपयोग करने की अनुमति देनी चाहिए ताकि इस प्रकार से डेटाबेस की 500 x संख्या में कनेक्शन की सीमा समाप्त हो जाए।

एक पठन क्वेरी पर, यह समन्वयक SELECTप्रत्येक डेटाबेस के लिए प्रश्न जारी कर सकता है, सभी परिणामों को मर्ज कर सकता है और उन्हें उस ग्राहक को वापस भेज सकता है जिसने पढ़ने का अनुरोध किया था।

यह बुरा विचार है क्योंकि:

  • यह विचार ... ahem .. over-engineering की तरह लगता है? के रूप में अच्छी तरह से (बैकअप आदि ..) का प्रबंधन करने के लिए एक बुरा सपना होगा। यह निर्माण और रखरखाव और यह एक तरह लगता है, जब तक यह बिल्कुल जरूरी है करने के लिए जटिल है KISS उल्लंघन।
  • यह संगति का त्याग करता है । यदि हम इस विचार के साथ चलते हैं, तो कई DB के लेन-देन करना एक नहीं है।

3
तुम्हारी अड़चन कहां है? आप अपने कनेक्शन पूल का उल्लेख कर रहे हैं, लेकिन यह केवल समानांतरवाद को प्रभावित करता है, न कि प्रति इंच गति। यदि आपके पास 500 कनेक्शन हैं और उदाहरण के लिए 2000QPS, तो यह ठीक काम करना चाहिए यदि प्रत्येक क्वेरी 250ms के भीतर पूरी होती है जो कि एक लूओंग समय है। 15ms से ऊपर क्यों है? यह भी ध्यान दें कि एक Paa का उपयोग करके आप महत्वपूर्ण अनुकूलन अवसर दे रहे हैं, जैसे कि डेटाबेस हार्डवेयर को स्केल करना या प्राथमिक डेटाबेस पर लोड को कम करने के लिए रीड-रेप्लिका का उपयोग करना। जब तक तैनाती आपकी सबसे बड़ी समस्या नहीं है तब तक हरोकू इसके लायक नहीं है।
आमोन

@amon टोंटी वास्तव में कनेक्शन पूल है। मैं ANALYZEस्वयं प्रश्नों पर चला हूं और वे कोई समस्या नहीं हैं। मैंने कनेक्शन पूल परिकल्पना का परीक्षण करने के लिए एक प्रोटोटाइप भी बनाया है और सत्यापित किया है कि यह वास्तव में समस्या है। डेटाबेस और सर्वर स्वयं विभिन्न मशीनों पर रहते हैं इसलिए विलंबता। इसके अलावा, हम हरोकू को छोड़ना नहीं चाहते हैं, जब तक कि पूरी तरह से आवश्यक नहीं है, तैनाती के बारे में चिंतित नहीं होना हमारे लिए बहुत बड़ा प्लस है।
निक किरियाकिड्स

1
कहा जा रहा है, मैं समझता हूं कि सूक्ष्म-अनुकूलन हैं जो मैं कर सकता था जो मुझे वर्तमान समस्या को हल करने में मदद करेगा । मुझे आश्चर्य है कि अगर मेरी समस्या का एक मापनीय वास्तु समाधान है।
निक किरियाकिड्स

3
आपने वास्तव में कैसे सत्यापित किया कि कनेक्शन पूल समस्या है? @amon अपनी गणना में सही है। select null500 कनेक्शन जारी करने का प्रयास करें । मुझे यकीन है कि आप पाएंगे कि कनेक्शन पूल वहां की समस्या नहीं है।
usr

1
यदि चुनिंदा अशक्त समस्याग्रस्त है तो आप शायद सही हैं। हालांकि यह दिलचस्प होगा कि वह सारा समय कहाँ बिताया जाता है। कोई भी नेटवर्क इतना धीमा नहीं है।
usr

जवाबों:


9

आगत प्रवाह

यह स्पष्ट नहीं है कि आपकी 1000 घटनाएं / दूसरी चोटियों का प्रतिनिधित्व करती हैं या यदि यह एक निरंतर भार है:

  • यदि यह एक चोटी है, तो आप DB सर्वर पर लोड को लंबे समय तक फैलाने के लिए बफर के रूप में एक संदेश कतार का उपयोग कर सकते हैं;
  • यदि यह निरंतर लोड है, तो अकेले संदेश कतार पर्याप्त नहीं है, क्योंकि DB सर्वर कभी भी पकड़ में नहीं आ सकेगा। फिर आपको एक वितरित डेटाबेस के बारे में सोचना होगा।

प्रस्तावित समाधान

वास्तव में, दोनों ही मामलों में, मैं एक काफ्का आधारित घटना-धारा के लिए जाऊंगा :

  • सभी घटनाओं को व्यवस्थित रूप से एक काफ्का विषय पर प्रकाशित किया जाता है
  • एक उपभोक्ता घटनाओं की सदस्यता लेगा और उन्हें डेटाबेस में संग्रहीत करेगा।
  • एक क्वेरी प्रोसेसर क्लाइंट से अनुरोधों को हैंडल करेगा और DB को क्वेरी करेगा।

यह सभी स्तरों पर अत्यधिक स्केलेबल है:

  • यदि DB सर्वर अड़चन है, तो बस कई उपभोक्ताओं को जोड़ें। प्रत्येक विषय की सदस्यता ले सकता है, और एक अलग डीबी सर्वर को लिख सकता है। हालाँकि, यदि वितरण DB सर्वरों में बेतरतीब ढंग से होता है, तो क्वेरी प्रोसेसर DB सर्वर को लेने और कई DB सर्वरों को क्वेरी करने की भविष्यवाणी नहीं कर पाएगा। यह क्वेरी की तरफ एक नई अड़चन पैदा कर सकता है।
  • इसलिए डीबी वितरण योजना का अनुमान कई विषयों (उदाहरण के लिए, चाबियों या संपत्तियों के समूहों का उपयोग करके, डीबी को एक अनुमान के मुताबिक तर्क के अनुसार विभाजित करने के लिए) में आयोजित किया जा सकता है।
  • यदि इनपुट संदेशों की बढ़ती बाढ़ को संभालने के लिए एक संदेश सर्वर पर्याप्त नहीं है, तो आप कई भौतिक सर्वरों में कफका विषयों को वितरित करने के लिए कफका विभाजन जोड़ सकते हैं ।

ग्राहकों को डीबी में अभी तक नहीं लिखा गया घटनाओं की पेशकश

आप चाहते हैं कि आपके ग्राहक पाइप में अभी भी सूचना तक पहुँच पाने में सक्षम हों और अभी तक डीबी को न लिखे हों। यह थोड़ा और नाजुक है।

विकल्प 1: db प्रश्नों के पूरक के लिए कैश का उपयोग करना

मैंने गहराई से विश्लेषण नहीं किया है, लेकिन मेरे दिमाग में आने वाला पहला विचार कफ़्का विषयों के क्वेरी प्रोसेसर (उपभोक्ताओं) को उपभोक्ता बनाना होगा, लेकिन एक अलग काफ़्का उपभोक्ता समूह में । अनुरोध प्रोसेसर तब सभी संदेश प्राप्त करेगा जो DB लेखक को प्राप्त होगा, लेकिन स्वतंत्र रूप से। यह उन्हें एक स्थानीय कैश में रख सकता है। उसके बाद क्वेरीज़ DB + cache (+ डुप्लिकेट के उन्मूलन) पर चलेगी।

तब डिजाइन इस तरह दिखेगा:

यहाँ छवि विवरण दर्ज करें

इस क्वेरी लेयर की मापनीयता अधिक क्वेरी प्रोसेसर (प्रत्येक अपने उपभोक्ता समूह में) जोड़कर हासिल की जा सकती है।

विकल्प 2: एक दोहरी एपीआई डिज़ाइन करें

एक बेहतर दृष्टिकोण IMHO एक दोहरी एपीआई की पेशकश करेगा (अलग उपभोक्ता समूह के तंत्र का उपयोग करें):

  • DB और / या एनालिटिक्स में घटनाओं तक पहुँचने के लिए एक क्वेरी एपीआई
  • एक स्ट्रीमिंग एपीआई जो विषय से सीधे संदेशों को अग्रेषित करता है

लाभ यह है कि आप ग्राहक को यह तय करने देते हैं कि क्या दिलचस्प है। इससे बच सकते हैं कि आप व्यवस्थित रूप से डीबी डेटा को हौसले से कैश किए गए डेटा के साथ मर्ज करें, जब क्लाइंट केवल नई आने वाली घटनाओं में रुचि रखता है। यदि ताजा और संग्रहीत घटनाओं के बीच नाजुक विलय वास्तव में आवश्यक है, तो ग्राहक को इसे व्यवस्थित करना होगा।

वेरिएंट

मैंने कफ़का प्रस्तावित किया क्योंकि यह बहुत अधिक मात्रा में लगातार संदेशों के साथ डिज़ाइन किया गया है ताकि आप ज़रूरत पड़ने पर सर्वर को पुनः आरंभ कर सकें।

आप RabbitMQ के साथ एक समान वास्तुकला का निर्माण कर सकते हैं। हालाँकि यदि आपको लगातार कतारों की आवश्यकता है, तो यह प्रदर्शन को कम कर सकता है । इसके अलावा, जहां तक ​​मुझे पता है, रैबिटएमक्यू के साथ कई पाठकों (जैसे लेखक + कैश) द्वारा समान संदेशों की समानांतर खपत को प्राप्त करने का एकमात्र तरीका कतारों का क्लोन बनाना है । तो एक उच्च मापनीयता अधिक मूल्य पर आ सकती है।


तारकीय; आपका क्या मतलब है a distributed database (for example using a specialization of the server by group of keys)? इसके अलावा खरगोश की जगह कफ्का क्यों? क्या एक को दूसरे पर चुनने का कोई विशेष कारण है?
निक Kyriakides 7

@NicholasKyriakides धन्यवाद! 1) मैं बस कई स्वतंत्र डेटाबेस सर्वरों के बारे में सोच रहा था, लेकिन एक स्पष्ट विभाजन योजना (कुंजी, भूगोल, आदि) के साथ जो प्रभावी रूप से आदेशों को भेजने के लिए इस्तेमाल किया जा सकता है। 2) सहज रूप से , हो सकता है क्योंकि काफ्का बहुत उच्च थ्रूपुट के लिए डिज़ाइन किया गया है जिसमें लगातार संदेशों को आपके सर्वर को पुनरारंभ करने की आवश्यकता होती है।)। मुझे यकीन नहीं है कि RabbitMQ वितरित परिदृश्यों के लिए उतना ही लचीला है, और लगातार कतारें प्रदर्शन को कम करती हैं
Christophe

1) इसलिए यह मेरे Use multiple databasesविचार से काफी मिलता-जुलता है लेकिन आप कह रहे हैं कि मुझे बेतरतीब ढंग से (या राउंड-रॉबिन) किसी भी डेटाबेस को संदेश वितरित नहीं करना चाहिए। सही?
निक किरियाकिड्स

हाँ। मेरा पहला विचार यादृच्छिक वितरण के लिए नहीं जाना होगा क्योंकि यह प्रश्नों के लिए प्रसंस्करण भार को बढ़ा सकता है (दोनों समय के कई DBs के iequery)। आप वितरित डीबी इंजन (उदाहरण के लिए?) पर भी विचार कर सकते हैं। लेकिन किसी भी सूचित विकल्प को बनाने के लिए डीबी के उपयोग के पैटर्न की अच्छी समझ की आवश्यकता होगी (डीबी में और क्या है, यह कितनी बार क्वियर किया गया है, किस तरह के प्रश्न हैं, व्यक्तिगत घटनाओं से परे लेन-देन संबंधी बाधाएं हैं, आदि ...)।
क्रिस्टोफ

3
बस इतना कहना चाहता हूं कि भले ही काफ्का बहुत उच्च थ्रूपुट दे सकता है, यह शायद ज्यादातर लोगों की जरूरतों से परे है। मैंने पाया कि काफ्का और इसकी एपीआई से निपटना हमारे लिए एक बड़ी गलती थी। RabbitMQ कोई
स्लैश

11

मेरा अनुमान है कि आपको अधिक सावधानी से एक दृष्टिकोण का पता लगाने की आवश्यकता है जिसे आपने अस्वीकार कर दिया है

  • हमारे सर्वर पर घटनाओं को दर्ज करें

मेरा सुझाव LMAX वास्तुकला के बारे में प्रकाशित विभिन्न लेखों के माध्यम से पढ़ना शुरू करना होगा । वे अपने उपयोग के मामले के लिए उच्च मात्रा में बैचिंग का काम करने में कामयाब रहे, और यह संभव हो सकता है कि आपके व्यापार के उतार-चढ़ाव उनकी तरह दिखें।

इसके अलावा, आप यह देखना चाहते हैं कि क्या आप पढ़े-लिखे तरीके से बाहर निकल सकते हैं - आदर्श रूप से आप उन्हें स्वतंत्र रूप से लिखने में सक्षम होना चाहेंगे। इसका मतलब है कि CQRS (कमांड क्वेरी जिम्मेदारी सेग्रीगेशन) में देख सकते हैं।

सर्वर पुनः आरंभ कर सकता है जबकि घटनाओं की गणना की जा रही है, जिससे हमें एनकेड घटनाओं को खोना पड़ता है।

एक वितरित प्रणाली में, मुझे लगता है कि आप बहुत आश्वस्त हो सकते हैं कि संदेश खो जाने वाले हैं। आप अपने अनुक्रम अवरोधों (उदाहरण के लिए - यह सुनिश्चित करने के लिए कि टिकाऊ भंडारण होता है-घटना से पहले प्रणाली के बाहर साझा किया जाता है) को सुनिश्चित करने के बारे में विवेकपूर्ण होने से इसके प्रभाव को कम करने में सक्षम हो सकते हैं।

  • उन्हें प्रबंधित करने के लिए केंद्रीय डीबी-समन्वयक सर्वर के साथ संदेशों के एक हिस्से को सहेजने वाले कई डेटाबेस का उपयोग करें

हो सकता है - डेटा को शार्प करने के लिए प्राकृतिक स्थान हैं या नहीं, यह देखने के लिए मुझे अपनी व्यापारिक सीमाओं को देखने की अधिक संभावना होगी।

ऐसे मामले हैं जहां डेटा खोना एक स्वीकार्य व्यापार है?

खैर, मुझे लगता है कि वहाँ हो सकता है, लेकिन वह नहीं है जहाँ मैं जा रहा था। मुद्दा यह है कि डिज़ाइन को संदेश हानि की स्थिति में प्रगति के लिए आवश्यक मजबूती प्रदान करनी चाहिए।

यह अक्सर जैसा दिखता है वह सूचनाओं के साथ एक पुल आधारित मॉडल है। प्रदाता एक ऑर्डर किए गए टिकाऊ स्टोर में संदेश लिखते हैं। उपभोक्ता स्टोर से संदेशों को खींचता है, अपने स्वयं के उच्च पानी के निशान को ट्रैक करता है। पुश सूचनाओं का उपयोग एक विलंबता कम करने वाले उपकरण के रूप में किया जाता है - लेकिन यदि अधिसूचना खो जाती है, तो संदेश अभी भी प्राप्त होता है (अंततः) क्योंकि उपभोक्ता एक नियमित समय पर खींच रहा है (अंतर यह है कि यदि अधिसूचना प्राप्त होती है, तो पुल जल्द ही होता है) )।

उड़ी दहन (पहले से एंडी द्वारा संदर्भित ) और ग्रेग यंग द्वारा पॉलीग्लॉट डेटा के बिना विश्वसनीय लेनदेन के बिना विश्वसनीय मैसेजिंग देखें ।


In a distributed system, I think you can be pretty confident that messages are going to get lost। वास्तव में? ऐसे मामले हैं जहां डेटा खोना एक स्वीकार्य व्यापार है? मैं इस धारणा के तहत था कि डेटा खोना = विफलता।
निक किरियाकिड्स

1
@ निकोलस कैरिकैड्स, यह आमतौर पर स्वीकार्य नहीं है, इसलिए ओपी ने घटना को छोड़ने से पहले एक टिकाऊ स्टोर पर लिखने की संभावना का सुझाव दिया। उदी दहन द्वारा इस लेख और इस वीडियो की जांच करें जहां वह समस्या को अधिक विस्तार से संबोधित करता है।
एंडी

6

अगर मैं सही तरीके से समझूं तो वर्तमान प्रवाह है:

  1. प्राप्त करें और घटना (मैं HTTP के माध्यम से ग्रहण करता हूं?)
  2. पूल से एक कनेक्शन का अनुरोध करें।
  3. घटना को डीबी में डालें
  4. पूल के लिए कनेक्शन जारी करें।

यदि ऐसा है तो मुझे लगता है कि डिजाइन में पहला बदलाव हर घटना पर पूल में आपके यहां तक ​​कि कोड रिटर्न कनेक्शन को रोकने के लिए होगा। इसके बजाय सम्मिलन थ्रेड्स / प्रक्रियाओं का एक पूल बनाएं जो डीबी कनेक्शन की संख्या के साथ 1-टू -1 है। ये प्रत्येक एक समर्पित DB कनेक्शन रखेंगे।

समवर्ती कतार के कुछ प्रकार का उपयोग करते हुए, आपके पास फिर ये धागे समवर्ती कतार से संदेश खींचते हैं और उन्हें सम्मिलित करते हैं। सिद्धांत रूप में, उन्हें कभी भी पूल में कनेक्शन लौटाने या नए अनुरोध करने की आवश्यकता नहीं होती है, लेकिन कनेक्शन खराब होने की स्थिति में आपको इसे संभालने की आवश्यकता हो सकती है। धागा / प्रक्रिया को मारना और एक नई शुरुआत करना सबसे आसान हो सकता है।

यह कनेक्शन पूल ओवरहेड को प्रभावी ढंग से समाप्त करना चाहिए। आप निश्चित रूप से प्रत्येक कनेक्शन पर प्रति सेकंड कम से कम 1000 / कनेक्शन घटनाओं को धक्का देने में सक्षम होने की आवश्यकता होगी। आप एक ही टेबल पर 500 कनेक्शन काम कर सकते हैं क्योंकि DB पर विवाद आ सकता है, क्योंकि आप अलग-अलग संख्या में कनेक्शन की कोशिश कर सकते हैं, लेकिन यह पूरी तरह से अलग सवाल है। एक और बात पर विचार करने के लिए बैच आवेषण का उपयोग होता है यानी प्रत्येक थ्रेड कई संदेशों को खींचता है और एक ही बार में उन्हें धक्का देता है। इसके अलावा, एक ही पंक्तियों को अपडेट करने का प्रयास करने वाले कई कनेक्शन रखने से बचें।


5

मान्यताओं

मैं मान रहा हूं कि आपके द्वारा वर्णित लोड स्थिर है, क्योंकि इसे हल करने के लिए अधिक कठिन परिदृश्य है।

मैं यह भी मानने जा रहा हूँ कि आपके पास अपनी वेब एप्लिकेशन प्रक्रिया के बाहर ट्रिगर, लंबे समय तक चलने वाले वर्कलोड चलाने का कोई तरीका है।

समाधान

यह मानते हुए कि आपने अपनी अड़चन - अपनी प्रक्रिया और पोस्टग्रेज डेटाबेस के बीच विलंबता की सही पहचान कर ली है - जिसे हल करना प्राथमिक समस्या है। समाधान को प्राप्त करने के बाद व्यावहारिक रूप से जितनी जल्दी हो सके घटनाओं को पढ़ने के इच्छुक अन्य ग्राहकों के साथ अपनी स्थिरता के लिए खाते की आवश्यकता होती है।

विलंबता समस्या को हल करने के लिए, आपको उस तरीके से काम करने की आवश्यकता है जो संग्रहीत किए जाने वाले प्रति घटना में विलंबित विलंब की मात्रा को कम करता है। यह वह महत्वपूर्ण चीज है जिसे आपको प्राप्त करने की आवश्यकता है यदि आप हार्डवेयर बदलने के इच्छुक या सक्षम नहीं हैं । यह देखते हुए कि आप पीएएस सेवाओं पर हैं और हार्डवेयर या नेटवर्क पर कोई नियंत्रण नहीं है, प्रति घटना की विलंबता को कम करने का एकमात्र तरीका कुछ प्रकार के बैच लेखन के साथ होगा।

आपको स्थानीय स्तर पर होने वाली घटनाओं की एक पंक्ति को संग्रहीत करने की आवश्यकता होगी जो समय-समय पर आपके db पर फ्लश हो जाती हैं और लिखी जाती हैं, या तो एक बार दिए गए आकार तक पहुँच जाती है, या समय की एक विस्तृत राशि के बाद। एक प्रक्रिया को स्टोर पर फ्लश को ट्रिगर करने के लिए इस कतार की निगरानी करने की आवश्यकता होगी। अपनी पसंद की भाषा में समय-समय पर प्रवाहित होने वाली समवर्ती कतार को प्रबंधित करने के तरीके के बारे में बहुत सारे उदाहरण होने चाहिए - यहां लोकप्रिय सेरिलॉग लॉगिंग लाइब्रेरी के आवधिक बैचिंग सिंक से C # में एक उदाहरण है

यह SO उत्तर Postgres में डेटा को फ्लश करने के सबसे तेज़ तरीके का वर्णन करता है - हालाँकि इसे आपके बैचिंग को डिस्क पर कतार में संग्रहीत करने की आवश्यकता होगी, और जब आपकी डिस्क हेरोकू में रिबूट पर गायब हो जाती है, तो वहाँ एक समस्या का समाधान होने की संभावना है।

बाधा

एक अन्य उत्तर में पहले ही CQRS का उल्लेख किया गया है , और यह बाधा के समाधान के लिए सही दृष्टिकोण है। आप पढ़े गए मॉडलों को हाइड करना चाहते हैं क्योंकि प्रत्येक घटना संसाधित होती है - एक मध्यस्थ पैटर्न किसी घटना को एनकैप्सुलेट करने में मदद कर सकता है और इसे कई हैंडलर प्रक्रिया में वितरित कर सकता है। तो एक हैंडलर आपके रीड मॉडल में ईवेंट को जोड़ सकता है जो इन-मेमोरी है जो क्लाइंट क्वेरी कर सकते हैं, और एक अन्य हैंडलर अपने अंतिम रूप से लिखे गए ईवेंट के लिए इवेंट को कतारबद्ध करने के लिए जिम्मेदार हो सकता है।

CQRS का मुख्य लाभ यह है कि आप अपने वैचारिक पढ़ने और लिखने के मॉडल को कम कर रहे हैं - जो कि आपके द्वारा एक मॉडल में लिखने का एक फैंसी तरीका है, और आप एक और पूरी तरह से अलग मॉडल से पढ़ते हैं। CQRS से स्केलेबिलिटी का लाभ प्राप्त करने के लिए आप आमतौर पर यह सुनिश्चित करना चाहते हैं कि प्रत्येक मॉडल को अलग-अलग तरीके से संग्रहीत किया जाए जो कि इसके उपयोग पैटर्न के लिए इष्टतम हो। इस मामले में हम एक समग्र रीड मॉडल का उपयोग कर सकते हैं - उदाहरण के लिए, एक रेडिस कैश, या बस इन-मेमरी - यह सुनिश्चित करने के लिए कि हमारे रीड तेज़ और सुसंगत हैं, जबकि हम अभी भी अपने डेटा को लिखने के लिए अपने ट्रांजेक्शनल डेटाबेस का उपयोग करते हैं।


3

डीबी कनेक्शन पूल की तुलना में ईवेंट तेजी से आ सकते हैं

यह एक समस्या है अगर प्रत्येक प्रक्रिया को एक डेटाबेस कनेक्शन की आवश्यकता होती है। सिस्टम को डिज़ाइन किया जाना चाहिए ताकि आपके पास श्रमिकों का एक पूल हो जहां प्रत्येक कार्यकर्ता को केवल एक डेटाबेस कनेक्शन की आवश्यकता हो और प्रत्येक कार्यकर्ता कई घटनाओं की प्रक्रिया कर सके।

संदेश कतार का उपयोग उस डिज़ाइन के साथ किया जा सकता है, आपको संदेश निर्माता (ओं) की आवश्यकता होती है जो घटनाओं को संदेश कतार में ले जाते हैं और कर्मचारी (उपभोक्ता) कतार से संदेशों को संसाधित करते हैं।

अन्य ग्राहक समवर्ती घटनाओं को पढ़ना चाहते हैं

यह अड़चन तभी संभव है जब डेटाबेस में बिना किसी प्रोसेसिंग (रॉ इवेंट्स) के स्टोर किए गए इवेंट। यदि डेटाबेस में संग्रहीत होने से पहले घटनाओं को संसाधित किया जा रहा है, तो घटनाओं को प्राप्त करने का एकमात्र तरीका डेटाबेस से है।

यदि ग्राहक केवल कच्ची घटनाओं को क्वेरी करना चाहते हैं, तो मैं सुझाव दूंगा कि लोचदार खोज जैसे खोज इंजन का उपयोग करें। यहां तक ​​कि आपको मुफ्त में क्वेरी / खोज एपीआई भी मिलेगा।

यह देखते हुए कि डेटाबेस में सहेजे जाने से पहले यह ईवेंट को क्वेरी करता है, आपके लिए महत्वपूर्ण है, इलास्टिक सर्च जैसे सरल समाधान को काम करना चाहिए। आप मूल रूप से इसमें सभी घटनाओं को संग्रहीत करते हैं और समान डेटा को डेटाबेस में कॉपी करके नकल नहीं करते हैं।

लोचदार खोज को स्केल करना आसान है, लेकिन बुनियादी विन्यास के साथ भी यह काफी उच्च प्रदर्शन है।

जब आपको प्रसंस्करण की आवश्यकता होती है, तो आपकी प्रक्रिया ईएस से घटनाओं को प्राप्त कर सकती है, प्रक्रिया कर सकती है और उन्हें डेटाबेस में संग्रहीत कर सकती है। मुझे नहीं पता कि इस प्रसंस्करण से आपको किस प्रदर्शन स्तर की आवश्यकता है, लेकिन यह ईएस से घटनाओं की क्वेरी करने से पूरी तरह से अलग होगा। आपके पास वैसे भी कनेक्शन समस्या नहीं होनी चाहिए, क्योंकि आपके पास एक निश्चित संख्या में कार्यकर्ता और प्रत्येक एक डेटाबेस कनेक्शन हो सकता है।


2

1 k या 2k घटनाओं (5KB) प्रति सेकंड एक डेटाबेस के लिए इतना नहीं है अगर इसमें एक उपयुक्त स्कीमा और भंडारण इंजन है। जैसा कि @eddyce द्वारा एक या अधिक दासों के साथ एक मास्टर द्वारा सुझाए गए प्रश्नों को पढ़ने लिखने से अलग कर सकते हैं। कम DB कनेक्शन का उपयोग करने से आपको बेहतर समग्र थ्रूपुट मिलेगा।

अन्य ग्राहक समवर्ती घटनाओं को पढ़ना चाहते हैं

इन अनुरोधों के लिए, उन्हें मास्टर डीबी से भी पढ़ने की आवश्यकता होगी क्योंकि पढ़ने वाले दासों के लिए प्रतिकृति अंतराल होगा।

मैंने बहुत अधिक मात्रा में लिखने के लिए टोर्कबीडी इंजन के साथ (पेरकोना) MySQL का उपयोग किया है। वहाँ भी है MyRocks इंजन LSMtrees पर आधारित है जो लिखने के भार के लिए अच्छा है। इन दोनों इंजनों और संभावना के लिए भी PostgreSQL में लेन-देन अलगाव के लिए सेटिंग्स हैं और साथ ही सिंक व्यवहार के लिए प्रतिबद्ध हैं जो नाटकीय रूप से लेखन क्षमता बढ़ा सकते हैं। पूर्व में हमने 1s तक खोए हुए डेटा को स्वीकार किया था, जो db क्लाइंट को सूचित किया गया था। अन्य मामलों में नुकसान से बचने के लिए बैटरी-समर्थित एसएसडी थे।

MySQL स्वाद में अमेज़ॅन आरडीएस अरोरा का दावा है कि शून्य-लागत प्रतिकृति (मास्टर के साथ एक फाइल सिस्टम साझा करने वाले दासों के समान) के साथ 6x उच्चतर थ्रूपुट है। ऑरोरा पोस्टग्रैसक्यूएल स्वाद में एक अलग उन्नत प्रतिकृति तंत्र भी है।


पर्याप्त हार्डवेयर पर किसी भी अच्छी तरह से प्रशासित डेटाबेस को टीबीएच इस भार से निपटने में सक्षम होना चाहिए। ओपी की समस्या डेटाबेस प्रदर्शन लेकिन कनेक्शन विलंबता प्रतीत नहीं होती है; मेरा अनुमान है कि पाको प्रदाता एक अलग AWS क्षेत्र में एक Postgres उदाहरण बेच रहा है के रूप में Heroku है।
आमोन

1

मैं सबको एक साथ छोड़ दूँगा, यह कहना है, मैं एक केंद्रीकृत दृष्टिकोण छोड़ दूँगा: एकाधिक लिखते हैं कि अधिकतम पूल कनेक्शन चोटी के मुख्य कारणों में से एक है, जहां डीबी क्लस्टर का आविष्कार किया गया था, मुख्य रूप से आप लेखन को लोड नहीं करते हैं। db (s) अन्य डीबी द्वारा क्लस्टर में किए जा सकने वाले रीड रिक्वेस्ट के साथ, मैं एक मास्टर-स्लेव टोपोलॉजी के साथ प्रयास करूँगा, इसके अलावा - जैसा कि किसी और ने पहले ही उल्लेख किया है, आपके स्वयं के डीबी इंस्टॉलेशन होने से पूरे ट्यून करना संभव होगा सिस्टम यह सुनिश्चित करने के लिए कि प्रचार प्रसार समय सही ढंग से संभाला जाएगा।

सौभाग्य

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.