Rust में CQRS और Event Sourcing: उच्च प्रदर्शन के लिए आर्किटेक्चर

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

CQRS और Event Sourcing: जटिल सिस्टम के लिए 'ओवरकिल' नहीं, बल्कि जीवन रक्षक

\n\n

क्या आपने कभी ऐसी स्थिति का सामना किया है जहाँ Rust में लिखा आपका सिस्टम रीड रिक्वेस्ट को तो बखूबी संभाल लेता है, लेकिन राइट करते समय 'घुटनों पर आ जाता है'? या इसके विपरीत — आप पूरा परिवर्तन इतिहास बचाने के लिए रीड परफॉरमेंस का त्याग कर देते हैं? परिचित लग रहा है? तो CQRS और Event Sourcing की दुनिया में आपका स्वागत है।

\n\n

कई डेवलपर्स इन पैटर्न को 'भारी तोपखाना' मानते हैं, जो केवल C# या Java के एंटरप्राइज प्रोजेक्ट्स में ही उपयोगी होते हैं। लेकिन हाई-लोड सिस्टम (गेम सर्वर से लेकर फाइनेंशियल प्लेटफॉर्म तक) में Rust की बढ़ती लोकप्रियता के साथ, CQRS और Event Sourcing न केवल उपयोगी हो गए हैं — वे आवश्यक हो गए हैं। Rust अपने शून्य-लागत एब्स्ट्रैक्शन और सख्त टाइपिंग के साथ इन पैटर्न को लागू करने के लिए आदर्श भाषा है।

\n\n

इस लेख में हम केवल सिद्धांत पर बात नहीं करेंगे। हम Rust में काम करने वाला कोड लिखेंगे जिसे आप अपने प्रोजेक्ट्स में ढाल सकते हैं। आप सीखेंगे कि कमांड और क्वेरी के बीच जिम्मेदारी कैसे बांटें, वर्तमान स्थिति के बजाय इवेंट कैसे स्टोर करें, और यह सब आपके सिस्टम को कई गुना तेज कैसे बनाता है।

\n\n

CQRS और Event Sourcing क्या हैं? Rust डेवलपर के लिए सरल भाषा में

\n\n

कल्पना करें कि आप एक बैंक खाता संभाल रहे हैं। पारंपरिक CRUD मॉडल में, आपके पास एक 'खाता' टेबल होती है जहाँ वर्तमान बैलेंस स्टोर होता है। अगर आपको इतिहास देखना है, तो आप एक और 'लेन-देन' टेबल बनाते हैं। लेकिन क्या होगा अगर आपको सिर्फ बैलेंस नहीं, बल्कि यह जानना हो कि वह क्यों बदला? या किसी भी तारीख की स्थिति को पुनर्स्थापित करना हो?

\n\n

CQRS: बांटो और राज करो

\n\n

CQRS (Command Query Responsibility Segregation) एक सिद्धांत है जो ऑपरेशन को दो समूहों में विभाजित करता है:

\n
    \n
  • कमांड (Commands) — स्थिति बदलते हैं। ये डेटा नहीं लौटाते, केवल पुष्टि या त्रुटि देते हैं।
  • \n
  • क्वेरी (Queries) — केवल डेटा पढ़ते हैं। ये स्थिति नहीं बदलते।
  • \n
\n\n

Rust में यह विभाजन स्वाभाविक लगता है: कमांड और क्वेरी के प्रकार अलग-अलग स्ट्रक्चर हैं, और उनके हैंडलर अलग-अलग फंक्शन या मॉड्यूल हैं। यह सिर्फ 'अच्छी प्रैक्टिस' नहीं है, बल्कि पढ़ते समय आकस्मिक म्यूटेशन से बचने का एक तरीका है।

\n\n
// कमांड — स्थिति बदलता है\npub struct CreateOrder {\n    pub user_id: Uuid,\n    pub items: Vec<OrderItem>,\n}\n\n// क्वेरी — केवल पढ़ता है\npub struct GetOrderHistory {\n    pub user_id: Uuid,\n    pub limit: usize,\n}
\n\n

Event Sourcing: स्नैपशॉट नहीं, इतिहास स्टोर करें

\n\n

Event Sourcing एक दृष्टिकोण है जिसमें हम किसी ऑब्जेक्ट की वर्तमान स्थिति नहीं, बल्कि उस स्थिति तक ले जाने वाली घटनाओं (इवेंट) के अनुक्रम को स्टोर करते हैं। 1 जनवरी 2023 को खाते का बैलेंस जानना चाहते हैं? बस शुरुआत से उस तारीख तक सभी इवेंट को 'रीप्ले' करें।

\n\n

फायदे स्पष्ट हैं:

\n
    \n
  • ऑडिट — हर बदलाव दर्ज है।
  • \n
  • टाइम ट्रैवल — कोई भी पिछली स्थिति पुनर्स्थापित की जा सकती है।
  • \n
  • बग के प्रति लचीलापन — अगर कोड में गलती है, तो डेटा खोया नहीं है, बस गलत तरीके से 'रीप्ले' हुआ है।
  • \n
\n\n

व्यावहारिक उदाहरण: Rust में ऑर्डर प्रबंधन सिस्टम

\n\n

चलिए एक ऑनलाइन स्टोर के लिए मिनी-सिस्टम बनाते हैं। यह कमांड (ऑर्डर बनाना, आइटम जोड़ना) और क्वेरी (कार्ट देखना, ऑर्डर इतिहास) को संभालेगा। सारा तर्क इवेंट पर आधारित होगा।

\n\n

चरण 1: इवेंट और कमांड परिभाषित करें

\n\n

सबसे पहले डोमेन डिज़ाइन करें। Rust में हम इवेंट के लिए enum और कमांड के लिए सख्त स्ट्रक्चर का उपयोग करते हैं।

\n\n
use serde::{Deserialize, Serialize};\nuse uuid::Uuid;\n\n// इवेंट — अपरिवर्तनीय तथ्य\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub enum OrderEvent {\n    Created { order_id: Uuid, user_id: Uuid, timestamp: i64 },\n    ItemAdded { order_id: Uuid, item: Str                

ब्लॉग

पुस्तक अनुशंसाएँ