एक वितरित, घटना वाली व्यवस्था में निरंतरता बनाए रखने के लिए पैटर्न?


12

मैं हाल ही में इवेंट सोर्सिंग के बारे में पढ़ रहा हूं और वास्तव में इसके पीछे के विचारों को पसंद करता हूं, लेकिन निम्नलिखित समस्या के साथ फंस गया हूं।

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

अब, मान लें कि हमारे पास निम्नलिखित व्यावसायिक नियम हैं: प्रत्येक विशिष्ट उपयोगकर्ता के पास एक विशिष्ट उपयोगकर्ता नाम होना चाहिए।

यदि दो प्रक्रियाओं को एक ही उपयोगकर्ता नाम X के लिए एक उपयोगकर्ता पंजीकरण आदेश प्राप्त होता है, तो वे दोनों जांचते हैं कि X उपयोगकर्ता नाम की उनकी सूची में नहीं है, नियम दोनों प्रक्रियाओं के लिए मान्य है और वे दोनों स्टोर में "उपयोगकर्ता नाम X के साथ नया उपयोगकर्ता" संग्रह करते हैं ।

हमने अब एक असंगत वैश्विक स्थिति में प्रवेश किया है क्योंकि व्यापार नियम का उल्लंघन किया गया है (एक ही उपयोगकर्ता नाम के साथ दो अलग-अलग उपयोगकर्ता हैं)।

एक पारंपरिक एन सर्वर <-> 1 आरडीबीएमएस शैली प्रणाली में, डेटाबेस को सिंक्रनाइज़ेशन के केंद्रीय बिंदु के रूप में उपयोग किया जाता है जो इस तरह की विसंगतियों को रोकने में मदद करता है।

मेरा सवाल यह है: ईवेंट सॉर्ड सिस्टम आमतौर पर इस समस्या से कैसे निपटते हैं? क्या वे हर क्रम को क्रमिक रूप से संसाधित करते हैं (उदाहरण के लिए प्रक्रिया की मात्रा को सीमित करें जो स्टोर को 1 लिख सकती है)?


1
क्या इस तरह के प्रतिबंध को कोड द्वारा नियंत्रित किया जाता है या यह एक db विवशता है? एन घटनाओं को अनुक्रम में प्रेषित किया जा सकता है या नहीं किया जा सकता है ... एन इवेंट एक ही समय में एक दूसरे को डिस्क्राइब करने वाले सत्यापन के माध्यम से जा सकते हैं। यदि आदेश मायने रखता है तो आपको सत्यापन को सिंक करने की आवश्यकता होगी। या कतार में घटनाओं का उपयोग करने के लिए क्रमिक रूप से प्रेषण करें
Laiv

@Laiv सही। सादगी के लिए मैंने माना कि कोई डेटाबेस नहीं था, सभी राज्य स्मृति में रखे थे। क्रमिक रूप से एक कतार के माध्यम से विशिष्ट प्रकार के आदेशों को संसाधित करना एक विकल्प होगा, लेकिन ऐसा महसूस होता है कि यह जटिल निर्णय लेने वाला हो सकता है, जो आदेश दूसरों को अत्यधिक प्रभावित कर सकते हैं और मैं संभवतः सभी आदेशों को एक ही कतार में डाल रहा हूं, जो एक ही प्रक्रिया प्रसंस्करण आदेशों के लिए होती हैं : / उदाहरण के लिए अगर मेरे पास एक ब्लॉग पोस्ट पर टिप्पणी जोड़ने वाला उपयोगकर्ता है, तो "उपयोगकर्ता हटाएं", "उपयोगकर्ता को निलंबित करें", "ब्लॉग पोस्ट हटाएं", "ब्लॉग पोस्ट टिप्पणियों को अक्षम करें", आदि सभी को एक ही कतार में जाना चाहिए।
ओलिवियर लालोंडे

1
आप के साथ काम करने के लिए, कतारों या सेमाफोर के साथ काम करना आसान नहीं है। न तो संगामिति या घटना-स्रोत पैटर्न के साथ काम करने के लिए। लेकिन मूल रूप से सभी समाधान एक सिस्टम ऑर्केस्ट्रेटिंग इवेंट के ट्रैफ़िक के साथ समाप्त होते हैं। हालाँकि यह एक दिलचस्प प्रतिमान है। रेडिस की तरह ट्यूपल्स के लिए उन्मुख बाहरी कैश भी हैं जो नोड्स के बीच इस ट्रैफ़िक को प्रबंधित करने में मदद कर सकते हैं, जैसे किसी इकाई की अंतिम स्थिति को कैश करना या यदि इस तरह की इकाई को अभी संसाधित किया जा रहा है। इस तरह के घटनाक्रम में साझा किए गए कैश काफी सामान्य हैं। यह जटिल लग सकता है, लेकिन हार नहीं मानता;; यह काफी दिलचस्प है
लैवि

जवाबों:


6

एक पारंपरिक एन सर्वर <-> 1 आरडीबीएमएस शैली प्रणाली में, डेटाबेस को सिंक्रनाइज़ेशन के केंद्रीय बिंदु के रूप में उपयोग किया जाता है जो इस तरह की विसंगतियों को रोकने में मदद करता है।

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

यदि सभी N सर्वर अपने M कमांड के साथ एक ही स्ट्रीम में लिखने की कोशिश कर रहे हैं, तो ध्यान देना एक बड़ी समस्या बन जाती है। यहाँ सामान्य उत्तर आपके मॉडल में प्रत्येक ईवेंट के लिए एक इतिहास को आवंटित करना है। तो उपयोगकर्ता (बॉब) उपयोगकर्ता (ऐलिस) से एक अलग इतिहास होगा, और एक को दूसरे को नहीं लिखेंगे।

मेरा सवाल यह है: ईवेंट सॉर्ड सिस्टम आमतौर पर इस समस्या से कैसे निपटते हैं? क्या वे हर क्रम को क्रमिक रूप से पूरा करते हैं?

ग्रेग यंग ऑन सेट वैलिडेशन

क्या डोमेन लॉजिक विशेषताओं पर अद्वितीय विरोधाभासों को जाँचने के लिए सर्विस लेयर में व्यापार तर्क को स्थानांतरित किए बिना एक शानदार तरीका है?

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

कुछ मामलों में, जहां आपका ईवेंट स्टोर सेट वैलिडेशन (यानी: रिलेशनल डेटाबेस) में अच्छा है, तो आप उसी लेन-देन में "अद्वितीय नाम" तालिका में लिखकर आवश्यकता को लागू करते हैं जो घटनाओं को बनाए रखता है।

कुछ मामलों में, आप केवल एक ही स्ट्रीम में प्रकाशित उपयोगकर्ता के सभी नाम (जो आपको अपने डोमेन मॉडल के भाग के रूप में स्मृति में नामों के सेट का मूल्यांकन करने की अनुमति देता है) को लागू करके आवश्यकता को लागू कर सकते हैं। - इस मामले में, दो प्रक्रियाएं "स्ट्रीम इतिहास" को अपडेट करने का प्रयास करेंगी, लेकिन तुलना-और-स्वैप संचालन में से एक विफल हो जाएगा, और उस आदेश की पुनर्प्राप्ति संघर्ष का पता लगाने में सक्षम होगी।


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

2) मुझे अस्थायी विसंगतियों को स्वीकार करने और अंततः उनकी मरम्मत करने का विचार भी पसंद है, लेकिन मुझे यकीन नहीं है कि मैं इसके लिए एक विश्वसनीय तरीके से कैसे कोड करूंगा ... शायद एक समर्पित प्रक्रिया है जो घटनाओं को क्रमिक रूप से मान्य करता है और जब यह पता चलता है तो रोलबैक ईवेंट बनाता है। कुछ गलत हो गया? धन्यवाद!
ओलिवियर लालोंडे

(1) मैं "नई घटनाओं" के बजाय "इतिहास का नया संस्करण" कहूंगा, लेकिन आपके पास विचार है; केवल इतिहास को प्रतिस्थापित करें यदि यह वह है जिसकी हम अपेक्षा कर रहे हैं।
VoiceOfUnreason

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

2

लगता है कि आप उपयोगकर्ता पंजीकरण के लिए एक व्यावसायिक प्रक्रिया ( sagaसंदर्भ में Domain Driven Design) लागू कर सकते हैं जहां उपयोगकर्ता को एक की तरह व्यवहार किया जाता है CRDT

साधन

  1. https://doc.akka.io/docs/akka/current/distributed-data.html http://archive.is/t0QIx

  2. "अक्का के साथ CRDTs वितरित डेटा" https://www.slideshare.net/markusjura/crdts-with-akka-distributed-data के बारे में जानने के लिए

    • CmRDTs - ऑपरेशन आधारित CRDTs
    • CvRDTs - राज्य आधारित CRTDs
  3. स्काला में कोड उदाहरण https://github.com/akka/akka-samples/tree/master/akka-sample-distributed-data-scala । शायद "खरीदारी की टोकरी" सबसे उपयुक्त है।

  4. अक्का क्लस्टर की यात्रा - अक्का वितरित डेटा https://manuel.bernhardt.io/2018/01/03/tour-akka-cluster-akka-distributed-data/
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.