A look at how Tencent Games built service architecture based on CQRS and event sourcing patterns with Pulsar and ScyllaDB. Tencent Interactive Entertainment Group Global (IEG Global) के हिस्से के रूप में, Proxima Beta दुनिया भर के लाखों खिलाड़ियों को अद्वितीय, रोमांचक खेल लाने के लिए हमारी टीमों और स्टूडियो का समर्थन करने के लिए प्रतिबद्ध है। Level Infinite (विश्व प्रकाशन ब्रांड) में हमारी टीम हमारे व्यवसाय के लिए एक विस्तृत श्रृंखला के जोखिमों का प्रबंधन करने के लिए जिम्मेदार है – उदाहरण के लिए, धोखाधड़ी गतिविधियों और हानिकारक सामग्री। इस ब्लॉग में, हम इस वास्तविक समय घटना-चालित विश्लेषणात्मक प्रणाली का निर्माण करने के हमारे अनुभव को साझा करते हैं. सबसे पहले, हम जांच करेंगे कि क्यों हम अपने सेवा आर्किटेक्चर को आदेश और पूछताछ जिम्मेदारी विभाजन के आधार पर बनाते हैं ( ) और event sourcing पैटर्न के साथ और ScyllaDB. अगले, हम देखेंगे कि हम ScyllaDB का उपयोग कई गेमिंग सत्रों में घटनाओं को वितरित करने की समस्या को हल करने के लिए कैसे करते हैं. अंत में, हम कवर करेंगे कि हम ScyllaDB कीबोर्ड स्पेस और डेटा पुनरावृत्ति का उपयोग कैसे करते हैं हमारे वैश्विक डेटा प्रबंधन को सरल बनाने के लिए। सीसीटीवी Pulsar के बारे में A Peek at the Use Case: Addressing Risks in Tencent Games चलो एक वास्तविक दुनिया के उदाहरण के साथ शुरू करते हैं कि हम क्या काम कर रहे हैं और चुनौतियों का सामना कर रहे हैं। यह एक स्क्रीनशॉट है Tower of Fantasy, एक 3D कार्रवाई रोल-प्ले खेल. खिलाड़ियों को विभिन्न कारणों से एक अन्य खिलाड़ी के खिलाफ एक रिपोर्ट जमा करने के लिए इस संवाद का उपयोग कर सकते हैं. यदि आप इसके लिए एक विशिष्ट CRUD सिस्टम का उपयोग करना चाहते हैं, तो आप अनुसरण के लिए उन रिकॉर्डों को कैसे रखेंगे? पहला चुनौती यह निर्धारित करना होगा कि किस टीम को इस फॉर्म को संग्रहीत करने के लिए डेटाबेस का स्वामित्व होगा. रिपोर्ट बनाने के लिए विभिन्न कारण हैं (अन्य नामक एक विकल्प सहित), इसलिए एक मामले को विभिन्न कार्यात्मक टीमों द्वारा संसाधित किया जा सकता है. हालांकि, हमारे संगठन में एक ही कार्यात्मक टीम नहीं है जो फॉर्म को पूरी तरह से स्वामित्व में रख सकती है. यही कारण है कि यह एक प्राकृतिक विकल्प है कि हम इस मामले को एक घटना के रूप में कैप्चर करते हैं, जैसे कि "एक मामले की रिपोर्ट करें." सभी जानकारी इस घटना में कैप्चर की जाती है. सभी कार्यात्मक टीमों को केवल इस घटना के लिए साइन अप करने और अपने स्वयं के फ़िल्टर करने की आवश्यकता होती है. यदि वे सोचते हैं कि मामला उनके डोमेन में पड़ता है, तो वे इसे बस कैप्चर कर सकते हैं और आगे की कार्रवाई शुरू कर सकते हैं. CQRS and Event Sourcing इस उदाहरण के पीछे सेवा वास्तुकला CQRS और घटना स्रोत पैटर्न पर आधारित है. यदि ये शर्तें आपके लिए नई हैं, तो चिंता न करें! इस समीक्षा के अंत तक, आपको इन अवधारणाओं का एक ठोस समझ होना चाहिए. और यदि आप उस बिंदु पर अधिक विवरण चाहते हैं, तो हमारे पर एक नज़र डालें . इस विषय को समर्पित ब्लॉग The first concept to understand here is event sourcing. The core idea behind event sourcing is that every change to a system’s state is captured in an event object and these event objects are stored in the order in which they were applied to the system state. In other words, instead of just storing the current state, we use an append-only store to record the entire series of actions taken on that state. This concept is simple but powerful as the events that represent every action are recorded so that any possible model describing the system can be built from the events. The next concept is CQRS, which stands for Command Query Responsibility Segregation. CQRS was coined by Greg Young over a decade ago and originated from the Command and Query Separation Principle. The fundamental idea is to create separate data models for reads and writes, rather than using the same model for both purposes. By following the CQRS pattern, every API should either be a command that performs an action, or a query that returns data to the caller – but not both. This naturally divides the system into two parts: the write side and the read side. यह विभाजन कई लाभ प्रदान करता है. उदाहरण के लिए, हम लागत दक्षता को अनुकूलित करने के लिए लिखने और पढ़ने की क्षमता को स्वतंत्र रूप से स्केलिंग कर सकते हैं. टीम कार्य के दृष्टिकोण से, अलग-अलग टीमें कम संघर्षों के साथ एक ही डेटा के अलग-अलग दृष्टिकोण बना सकती हैं. लिखने के पक्ष के उच्च स्तर का कार्यप्रवाह निम्नलिखित के रूप में संक्षेप में किया जा सकता है: कई गेमिंग सत्रों में होने वाले घटनाओं को एक सीमित संख्या में घटना प्रोसेसरों में डाला जाता है। कार्यान्वयन भी सरल है, आमतौर पर Pulsar, Kafka, या एक सरल पंक्ति प्रणाली शामिल है जो एक घटना स्टोर के रूप में कार्य करता है। . ब्लॉग से जुड़े अन्य समाचार हालांकि लाइन-आधारित सिस्टम आमतौर पर एक दिशा में प्रवाह को संभालने में कुशल होते हैं (उदाहरण के लिए, प्रशंसक-इन), वे विपरीत दिशा में प्रवाह को संभालने में उतने कुशल नहीं हो सकते हैं (उदाहरण के लिए, प्रशंसक-आधारित)। हमारे परिदृश्य में, गेमिंग सत्रों की संख्या बड़ी होगी, और एक सामान्य लाइन-आधारित सिस्टम अच्छी तरह से फिट नहीं होगा क्योंकि हम प्रत्येक गेमिंग सत्र के लिए एक समर्पित लाइन बनाने की अनुमति नहीं दे सकते हैं। आगे बढ़ने से पहले, यहां हमारी सेवा वास्तुकला का एक सारांश है। लिखने की तरफ से शुरू करते हुए, गेम सर्वर कमान अंतर्दृष्टि के माध्यम से हमारे सिस्टम में घटनाओं को भेजते रहते हैं और प्रत्येक घटना एक निश्चित प्रकार की गतिविधि का प्रतिनिधित्व करती है जो गेमप्ले सत्र में हुई थी. घटना प्रोसेसर प्रत्येक गेमप्ले सत्र के घटना प्रवाहों के खिलाफ निष्कर्ष या मीट्रिक का उत्पादन करते हैं और दो पक्षों के बीच एक पुल के रूप में कार्य करते हैं. पढ़ने की तरफ, हमारे पास गेम सर्वर या अन्य क्लाइंट हैं जो पूछताछ अंतर्दृष्टि के माध्यम से सर्वेक्षण मीट्रिक और निष्कर्षों को जारी रखते हैं और यदि असामान्य गतिविधियां देखी गई हैं तो आगे की कार्रवाई करते हैं। Time Series Events के लिए Distributed Queue-Like Event Store अब चलो देखते हैं कि हम ScyllaDB का उपयोग कई गेमिंग सत्रों में घटनाओं को वितरित करने की समस्या को हल करने के लिए कैसे करते हैं. वैसे, यदि आप गूगल करते हैं “Cassandra” और “queue”, तो आप एक दशक से अधिक समय पहले एक लेख से मिल सकते हैं जिसमें कहा गया है कि Cassandra का उपयोग एक लाइन के रूप में एक विरोधी पैटर्न है. हालांकि यह उस समय सच हो सकता था, मैं तर्क दूंगा कि यह आज केवल आंशिक रूप से सच है। प्रत्येक गेमप्ले सत्र के लिए घटनाओं के वितरण का समर्थन करने के लिए, हम सत्र आईडी का उपयोग विभाजन कुंजी के रूप में करते हैं ताकि प्रत्येक गेमप्ले सत्र में अपना खुद का विभाजन हो और किसी विशेष गेमप्ले सत्र से संबंधित घटनाओं को सत्र आईडी द्वारा कुशलता से रखा जा सकता है। प्रत्येक घटना में एक अद्वितीय घटना आईडी भी होता है, जो कि क्लस्टर की कुंजी के रूप में समय UUID है. एक ही विभाजन के भीतर के रिकॉर्ड क्लस्टर की कुंजी द्वारा वर्गीकृत होते हैं, इसलिए घटना आईडी को एक पंक्ति में स्थिति आईडी के रूप में इस्तेमाल किया जा सकता है. अंत में, ScyllaDB क्लाइंट को हाल ही में प्राप्त हुई घटना आईडी को ट्रैक करके नए आते हुए घटनाओं को कुशलता से प्राप्त किया जा सकता है. इस दृष्टिकोण का उपयोग करते समय ध्यान में रखने के लिए एक चेतावनी है: स्थिरता की समस्या। नवीनतम घटना आईडी को ट्रैक करके नए घटनाओं को प्राप्त करना इस धारणा पर निर्भर करता है कि भविष्य में एक छोटे से आईडी के साथ कोई भी घटना घटित नहीं होगी. हालांकि, यह धारणा हमेशा सच नहीं हो सकती है. उदाहरण के लिए, यदि दो नोड एक ही समय में दो घटना आईडी उत्पन्न करते हैं, तो एक छोटी आईडी के साथ एक घटना एक बड़े आईडी के साथ एक घटना से बाद में दर्ज की जा सकती है. यह समस्या, जिसे मैं "फैंथम रीडिंग" के रूप में संदर्भित करता हूं, SQL दुनिया में उस घटना के समान है जहां एक ही पूछताछ को दोहराना अन्य लेनदेन द्वारा किए गए अनियंत्रित परिवर्तनों के कारण अलग-अलग परिणाम दे सकता है। इस समस्या को हल करने के कई तरीके हैं. एक समाधान एक क्लस्टर-विश्व स्थिति बनाए रखना है, जिसे मैं "अब पहेडो" कहता हूं, जो सभी घटना प्रोसेसरों के बीच चलने वाले टाइमस्टैम्प का सबसे छोटा मूल्य आधारित है. प्रत्येक घटना प्रोसेसर को यह सुनिश्चित करना चाहिए कि सभी भविष्य के घटनाओं में वर्तमान टाइमस्टैम्प से बड़ा एक घटना आईडी है. Another important consideration is enabling TimeWindowCompactionStrategy, which eliminates the negative performance impact caused by tombstones. Accumulation of tombstones was a major issue that prevented the use of Cassandra as a queue before TimeWindowCompactionStrategy became available. अब चलो ScyllaDB का उपयोग करने के अलावा अन्य लाभों पर चर्चा करने के लिए आगे बढ़ते हैं। जटिल वैश्विक डेटा वितरण चुनौतियों को सरल करना चूंकि हम दुनिया भर में ग्राहकों की सेवा करने के लिए एक मल्टी-टेनेशन सिस्टम का निर्माण कर रहे हैं, इसलिए यह सुनिश्चित करना महत्वपूर्ण है कि विभिन्न क्षेत्रों के क्लस्टर में ग्राहक कॉन्फ़िगरेशन समान हैं। हमने इस समस्या को केवल सभी डेटा सेंटरों पर एक कुंजी स्थान पर डेटा पुनरावृत्ति की अनुमति देकर हल किया. इसका मतलब है कि एक डेटा सेंटर में किए गए किसी भी परिवर्तन को अंततः अन्य लोगों को फैलाया जाएगा. धन्यवाद ScyllaDB, साथ ही साथ DynamoDB और Cassandra, भारी उठाने के लिए जो इस चुनौतीपूर्ण समस्या को छोटा लगता है। आप सोच रहे हो सकते हैं कि किसी भी विशिष्ट आरडीबीएमएस का उपयोग करना एक ही परिणाम प्राप्त कर सकता है क्योंकि अधिकांश डेटाबेस डेटा रीप्लिकेशन का भी समर्थन करते हैं। यह सच है यदि किसी भी क्षेत्र में नियंत्रण पैनल का केवल एक उदाहरण चल रहा है. एक विशिष्ट प्राथमिक / प्रतिलिपि आर्किटेक्चर में, केवल प्राथमिक नोड पढ़ने / लिखने का समर्थन करता है जबकि प्रतिलिपि नोड केवल पढ़ने के लिए हैं. हालांकि, जब आपको विभिन्न क्षेत्रों पर नियंत्रण पैनल के कई उदाहरण चलाने की आवश्यकता होती है – उदाहरण के लिए, प्रत्येक किरायेदार के पास अपने घर क्षेत्र में चलने वाला नियंत्रण पैनल होता है, या यहां तक कि हर क्षेत्र में स्थानीय टीमों के लिए चलने वाला नियंत्रण पैनल होता है – यह एक विशि यदि आपने AWS DynamoDB का उपयोग किया है, तो आप ग्लोबल टेबल नामक एक सुविधा से परिचित हो सकते हैं, जो अनुप्रयोगों को स्थानीय रूप से पढ़ने और लिखने और वैश्विक रूप से डेटा तक पहुंचने की अनुमति देता है। डेटा कंटेनर के रूप में कुंजी स्थान अगला, आइए देखें कि हम वैश्विक डेटा वितरण की पारदर्शिता में सुधार करने के लिए डेटा कंटेनर के रूप में कुंजी स्थानों का उपयोग कैसे करते हैं। नीचे दिए गए चार्ट पर एक नज़र डालें. यह डेटा संरक्षण कानूनों द्वारा लगाए गए एक विशिष्ट डेटा वितरण समस्या के लिए एक समाधान दिखाता है. उदाहरण के लिए, मान लें कि क्षेत्र A अपने सीमाओं के बाहर कुछ प्रकार के डेटा को संसाधित करने की अनुमति देता है जब तक कि मूल प्रति को अपने क्षेत्र में रखा जाता है. एक उत्पाद मालिक के रूप में, आप यह सुनिश्चित कैसे कर सकते हैं कि आपके सभी आवेदन इस नियम का अनुपालन करते हैं? » » एक संभावित समाधान यह सुनिश्चित करने के लिए अंत से अंत (E2E) परीक्षण करना है कि अनुप्रयोगों को सही रूप से सही क्षेत्र में सही डेटा भेजने की उम्मीद की जाती है. इस दृष्टिकोण से अनुप्रयोग डेवलपर्स को डेटा वितरण को सही तरीके से लागू करने के लिए पूरी जिम्मेदारी लेने की आवश्यकता होती है. हालांकि, जब अनुप्रयोगों की संख्या बढ़ती है, तो प्रत्येक अनुप्रयोग के लिए इस समस्या को व्यक्तिगत रूप से संभालना असंभव हो जाता है और E2E परीक्षण भी समय और पैसा दोनों के मामले में अधिक से अधिक महंगा हो जाता है. कुंजी स्थानों पर डेटा पुनरावृत्ति को सक्षम करके, हम डेटा को सही ढंग से वितरित करने की जिम्मेदारी को दो कार्यों में विभाजित कर सकते हैं: 1) डेटा प्रकारों की पहचान और उनके गंतव्य की घोषणा करना, और 2) डेटा को कॉपी करना या अपेक्षित स्थानों पर स्थानांतरित करना। इन दो कर्तव्यों को अलग करके, हम अनुप्रयोगों से जटिल कॉन्फ़िगरेशन और नियमों को दूर कर सकते हैं. यह इसलिए है क्योंकि अन्य क्षेत्रों में डेटा को स्थानांतरित करने की प्रक्रिया अक्सर सबसे जटिल हिस्सा है, जैसे नेटवर्क सीमाओं को पार करना, ट्रैफ़िक को सही ढंग से एन्क्रिप्शन करना, और बाधाओं को संभालना। इन दो कार्यों को अलग करने के बाद, अनुप्रयोगों को केवल पहले चरण को सही ढंग से पूरा करने की आवश्यकता होती है, जो विकास चक्र के शुरुआती चरणों में परीक्षण के माध्यम से सत्यापित करना बहुत आसान होता है। अन्य लोगों के लिए टिप्स जो एक समान मार्ग लेते हैं अंत में, हम आपको उन महत्वपूर्ण सबक के साथ छोड़ देंगे जिन्हें हमने सीखा है, और जिन्हें हम अनुशंसा करते हैं कि आप आवेदन करें यदि आप हमारे समान मार्ग लेते हैं: When using ScyllaDB to handle time series data, such as using it as an event-dispatching queue, remember to use the . Time-Window Compaction Strategy डेटा वितरण के जिम्मेदारियों को अलग करने के लिए डेटा कंटेनर के रूप में कुंजी स्थानों का उपयोग करने पर विचार करें.This can make complex data distribution problems much easier to manage. अनुरोध पर तकनीकी बातचीत देखें यह लेख ScyllaDB Summit 2023 में प्रस्तुत एक तकनीकी बातचीत पर आधारित है. आप इस बातचीत को देखते हैं - साथ ही Discord, Epic Games, Disney, Strava, ShareChat और अधिक से इंजीनियरों की बातचीत भी - अनुरोध पर। अनुरोध पर तकनीकी बातचीत देखें