प्लेबुक
वितरित सिस्टम में CQRS (कमांड क्वेरी रिस्पॉन्सिबिलिटी सेग्रीगेशन): इवेंट, ब्रोकर और प्रोजेक्शन (CQRS 2)
वितरित सिस्टम में CQRS कैसे काम करता है? डोमेन इवेंट, संदेश ब्रोकर, प्रोजेक्शन, आउटबॉक्स, निष्क्रियता और अंतिम स्थिरता निर्णयों की शुरू से अंत तक जांच करें।
सीक्यूआरएस (कमांड क्वेरी रिस्पॉन्सिबिलिटी सेग्रीगेशन) - निर्णयों की शारीरिक रचना
भाग 3 का 4
The problem we are solving first
An order has been created. Inventory must know, notifications must send an email, analytics must prepare a report, and search must index the new order.
Order Service
→ HTTP call for Inventory
→ HTTP call for Notifications
→ HTTP call for Analytics
→ HTTP call for Search
Should the Order Service call each of them over HTTP? Every new capability expands the call chain, failure surface, and pressure to deploy together. No. The Order Service should share the business fact that happened; how it is used belongs to each consumer.
सीक्यूआरएस के पहले दो भागों में, हमने अलग किया कि कमांड और क्वेरी पक्ष पर अनुरोध कैसे आगे बढ़ता है। वितरित प्रणाली में नया प्रश्न यह है: एक बार ऑर्डर स्वीकार हो जाने के बाद, इन्वेंट्री, अधिसूचना, विश्लेषण और खोज टीमें इस परिवर्तन के बारे में सुरक्षित रूप से कैसे सीखती हैं?text POST /orders → Command Handler → OrderPlaced olayı → Outbox → Relay → Message Broker ├─ Inventory projection ├─ Notification consumer ├─ Analytics projection └─ Search read model घटना एक वास्तविक और अपरिवर्तनीय व्यावसायिक तथ्य है; OrderPlaced कोई इरादा नहीं है, यह एक तथ्य है जो घटित हुआ। ब्रोकर इवेंट को निर्माता से उपभोक्ता तक ले जाता है। उपभोक्ता अपनी जिम्मेदारी के लिए घटना को संसाधित करता है। प्रोजेक्शन इवेंट स्ट्रीम से पढ़ने के लिए उपयुक्त दृश्य तैयार करता है।
पहले उल्लेख पर अवधारणाएँ```text
📦 Domain event Geçmiş zamanda ifade edilen, iş alanında gerçekleşmiş değişmez bir gerçektir.
📦 Broker Mesajı kalıcılaştıran ve tüketicilere dağıtan iletişim katmanıdır.
📦 Projection Event'lerden belirli bir ekran veya sorgu için üretilen read modeldir.
📦 Idempotency
Aynı event iki kez gelirse sonucu ikinci kez değiştirmeme özelliğidir.
```एक कमांड कहता है PlaceOrder; यह सिस्टम से एक व्यवहार का अनुरोध करता है। सफल होने पर, OrderPlaced प्रकाशित किया जा सकता है। आदेश को अस्वीकार किया जा सकता है; घटना एक सच्चाई है जिसे अब आप बदल नहीं सकते।
ब्रोकर डिलीवरी अक्सर कम से कम एक बार होती है: वही संदेश दोबारा दिखाई दे सकता है। इसलिए उपभोक्ता को संदेश आईडी छिपाकर या लेनदेन को स्वाभाविक रूप से निष्क्रिय बनाकर डुप्लिकेट को सुरक्षित रूप से संभालना चाहिए।```text if processedEvents.contains(event.id): return
applyProjection(event) markProcessed(event.id)
## Why the design looks this way
~~~text
PlaceOrder → an intent.
OrderPlaced → a fact that happened.
~~~
We make this distinction **because** a command can fail, while an event is a completed fact other systems can safely react to.
- **Outbox** is needed **because** the broker and database do not share one ACID transaction.
- A **projection** is needed **because** an admin panel, mobile app, dashboard, and analytics need the same order in different shapes without loading the aggregate.
- **Idempotency** is needed **because** a broker can redeliver the same message for reliable delivery.
- A **saga** is needed **because** inventory must not remain reserved forever when payment fails in e-commerce.
- Most applications that use CQRS do not use Event Sourcing; they are independent decisions.
## एकल सेवा सीमा पार होने पर क्या परिवर्तन होता है?
एक ही एप्लिकेशन में, लेनदेन, डेटा रिकॉर्डिंग और साइड इफेक्ट्स को एक ही प्रक्रिया में प्रबंधित किया जा सकता है। जब सिस्टम वितरित होता है, तो इन्वेंट्री, ईमेल और रिपोर्टिंग का अपना जीवनचक्र होता है। किसी सेवा के लिए अल्पावधि में किसी अन्य सेवा के लिए समकालिक HTTP कॉल करना आसान लगता है; लेकिन प्रत्येक कॉल में विलंबता, त्रुटि प्रसार और सह-परिनियोजन दबाव शामिल होता है।
इवेंट-आधारित प्रवाह इस निर्भरता को डेटा अनुबंध पर ले जाता है। ऑर्डरिंग सेवा `OrderPlaced` इवेंट की स्कीमा के लिए ज़िम्मेदार है; स्टॉक सेवा केवल उस हिस्से का उपभोग करती है जिसकी उसे आवश्यकता होती है। निर्माता उपभोक्ता के डेटाबेस या रनटाइम को नहीं जानता है। स्वतंत्र तैनाती योग्यता स्वतंत्र अवलोकन के बिना जोखिम का विस्थापन मात्र है।
## लेनदेन सीमा से घटना को सुरक्षित रूप से हटाना
अनुभवहीन प्रवाह है:```text
Save order
→ Commit
→ Publish OrderPlaced
```यदि कमिट सफल है लेकिन प्रकाशन विफल रहता है, तो सिस्टम को ऑर्डर का पता चलता है, अन्य सेवाओं को नहीं। उल्टे क्रम में प्रकाशित करने और प्रतिबद्ध करने में विफलता भी एक भूत घटना उत्पन्न करती है। **आउटबॉक्स पैटर्न** एक ही स्थानीय लेनदेन में दो बार लिखता है:```text
Transaction
→ Order kaydını yaz
→ Outbox'a OrderPlaced kaydını yaz
→ Commit
Relay
→ Outbox kaydını broker'a ilet
→ teslim edildi olarak işaretle
```आउटबॉक्स वितरित लेनदेन स्थापित नहीं करता है; यह महत्वपूर्ण तथ्य को सुरक्षित करता है: यदि डेटाबेस में कोई ऑर्डर है, तो प्रकाशित होने वाली एक घटना है। रिले पुनः प्रयास कर सकता है. इसलिए, उपभोक्ता पक्ष पर निष्क्रियता की आवश्यकता समाप्त नहीं होती है।
**सीडीसी** डेटाबेस लॉग से परिवर्तन कैप्चर कर सकता है। सीडीसी मौजूदा डेटाबेस में परिवर्तन के प्रचार-प्रसार के लिए शक्तिशाली है; हालाँकि, डोमेन भाषा पर आपका नियंत्रण सीमित हो सकता है। दूसरी ओर, आउटबॉक्स एप्लिकेशन को स्पष्ट रूप से चयन करने की अनुमति देता है कि किस घटना का व्यावसायिक अर्थ है।
| प्रश्न | सीडीसी | आउटबॉक्स |
| --- | --- | --- |
| डोमेन भाषा द्वारा ईवेंट का चयन | सीमित | साफ़ और पूर्ण |
| आवेदन लेनदेन से लिंक | अप्रत्यक्ष | प्रत्यक्ष |
| उपभोक्ता निष्क्रियता की आवश्यकता | हाँ | हाँ |
## प्रक्षेपण: आशय-उन्मुख दृश्य, प्रतिलिपि नहीं
पढ़ा गया मॉडल, लिखे गए मॉडल की अधूरी प्रति नहीं है। उत्पाद सूची के लिए `ProductSearchRow` उत्पन्न किया जा सकता है और ऑपरेशन पैनल के लिए `OrderFulfilmentSummary` उत्पन्न किया जा सकता है। एक ही घटना अलग-अलग टीमों के अलग-अलग अनुमान पेश कर सकती है।```text
OrderPlaced
→ OrderSummaryProjection
→ { orderId, customerName, total, status }
OrderPlaced
→ InventoryProjection
→ { sku, reservedQuantity, availability }
```प्रक्षेपण पुनर्निर्माण योग्य होने चाहिए. जब कोड बदलता है या त्रुटि ठीक हो जाती है, तो इवेंट स्ट्रीम को नियंत्रित तरीके से दोबारा चलाया जाता है और नए रीड मॉडल को सत्यापित किया जाता है। इसके लिए इवेंट ऑर्डर, चेकपॉइंट, वर्जनिंग और रीप्ले स्पीड को मापा जाना चाहिए। प्रक्षेपण विलंब उत्पाद भाषा में दिखाई देना चाहिए: क्या उपयोगकर्ता द्वारा ऑर्डर देने के कुछ सेकंड बाद सूची में इसका दिखना स्वीकार्य है? इसका उत्तर एक व्यावसायिक निर्णय है, तकनीकी नहीं।
## ब्रोकर चुनना कोई ब्रांड पसंद नहीं है
दलाल; यह सॉर्टिंग, दृढ़ता, उपभोक्ता समूह, रीप्ले और त्रुटि कतार गारंटी प्रदान करता है। यदि क्रम उसी कुंजी के लिए महत्वपूर्ण है, तो एक विभाजन कुंजी डिज़ाइन की जानी चाहिए। यदि उपभोक्ता पिछड़ सकता है, तो अंतराल, पुनः प्रयास और डेड-लेटर रणनीतियों का पालन किया जाना चाहिए। यदि स्कीमा बदल रहा है, तो एक नया फ़ील्ड जोड़ें, पुराने फ़ील्ड को जल्दबाजी में न हटाएं; ईवेंट संस्करण को पश्चगामी संगत रहना चाहिए।
## इवेंट सोर्सिंग और CQRS एक ही चीज़ नहीं हैं
CQRS पढ़ने और लिखने की जिम्मेदारियों को अलग करता है। दूसरी ओर, इवेंट सोर्सिंग, वर्तमान पंक्ति के बजाय केवल-परिशिष्ट इवेंट स्ट्रीम से समग्र स्थिति उत्पन्न करती है। उनका उपयोग एक साथ किया जा सकता है; हालाँकि, CQRS के लिए इवेंट सोर्सिंग अनिवार्य नहीं है और इवेंट सोर्सिंग के लिए काफ्का अनिवार्य नहीं है। जब इवेंट सोर्सिंग का चयन किया जाता है, तो स्नैपशॉट, स्ट्रीम संस्करण और रीप्ले लागत अलग-अलग डिज़ाइन की जाती है।
## सागा: वितरित वर्कफ़्लो में मुआवज़े का निर्णय
एक ऑर्डर भुगतान, स्टॉक और शिपिंग चरणों से गुजर सकता है; ये चरण एकल ACID लेनदेन में फिट नहीं हो सकते। सागा प्रत्येक स्थानीय ऑपरेशन के लिए एक मुआवजा कदम परिभाषित करता है।```text
Order placed
→ reserve inventory
→ capture payment
→ create shipment
payment fails
→ release inventory
→ mark order failed
```**कोरियोग्राफी** सेवाओं को घटनाओं के साथ एक-दूसरे को ट्रिगर करने की अनुमति देती है; स्थानीय निर्भरता कम है, लेकिन पूरे प्रवाह का पालन करना मुश्किल हो जाता है। **ऑर्केस्ट्रेशन** प्रवाह को केंद्रीय प्रक्रिया प्रबंधक के साथ दृश्यमान बनाता है; बदले में, यह समन्वय जिम्मेदारी जोड़ता है।
## ऑपरेशनल चेकलिस्ट
1. क्या प्रत्येक घटना का नाम भूतकाल और व्यावसायिक भाषा में रखा गया है?
2. क्या आउटबॉक्स डेटाबेस रिकॉर्डिंग और इवेंट प्रकाशन के बीच के अंतर को पाटता है?
3. क्या यह उपभोक्ता डुप्लिकेट, कतार भ्रष्टाचार और देर से होने वाली घटनाओं के लिए सुरक्षित है?
4. क्या प्रक्षेपण जांच बिंदु, अंतराल और पुनर्निर्माण प्रक्रिया देखी जा सकती है?
5. क्या ईवेंट अनुबंध, रिलीज़ रणनीति और बैकवर्ड संगतता नियम के स्वामी स्पष्ट हैं?
6. क्या उत्पाद द्वारा स्वीकार की गई अंतिम स्थिरता विंडो उपयोगकर्ता को दिखाई देती है?
यदि इन प्रश्नों का उत्तर नहीं दिया जाता है, तो सिस्टम घटना-संचालित प्रतीत होता है; लेकिन विफलता-प्रेरित कार्य करता है।
## अक्सर भ्रमित होने वाले भेद```text
❌ Event = Command
✓ Command niyettir; event gerçekleşmiş gerçektir.
❌ Broker = Event Store
✓ Broker event'i taşır; Event Store domain geçmişinin kalıcı kaynağı olabilir.
❌ Projection = cache
✓ Cache hız için geçicidir; projection iş sorgusu için bilinçli bir read modeldir.
❌ At-least-once = hata
✓ Tekrar teslimat normaldir; consumer idempotent olmalıdır.
```## सच्ची एंड-टू-एंड स्ट्रीमिंग```text
POST /orders
→ Controller
→ Mediator.Send()
→ Validation + Authorization
→ Transaction Behavior
→ PlaceOrderHandler
→ Order aggregate
→ Order + Outbox commit
→ Relay
→ Broker
→ Projection consumer
→ Read database
→ GET /orders
→ Query Handler
→ OrderSummaryDto
→ Frontend
मुझे इस मॉडल का उपयोग कब करना चाहिए?
पहले तार्किक CQRS से शुरुआत करें: व्यावसायिक भाषा में कमांड को नाम दें, स्क्रीन की आवश्यकता के अनुसार क्वेरी को कम करें और लेनदेन सीमा को स्पष्ट करें। दलालों और अलग-अलग अनुमानों को केवल तभी जोड़ा जाना चाहिए जब स्वतंत्र उपभोक्ता, असममित रीड लोड, या पुन: चलाने योग्य एकीकरण की आवश्यकता सिद्ध हो।
यद्यपि प्रत्येक नए उपभोक्ता की लागत O(1) कोड परिवर्तन की तरह लग सकती है, परिचालन लागत निश्चित नहीं है: अनुबंध, डैशबोर्ड, अलार्म, पुनः प्रयास, स्वामित्व और परीक्षण परिदृश्य की आवश्यकता होती है।
##प्रतिबिंब
वितरित सीक्यूआरएस का वादा अधिक संदेश नहीं, बल्कि अधिक दृश्य जिम्मेदारियां हैं। घटनाएँ इतिहास को आगे बढ़ाती हैं, दलाल प्रवाह को आगे बढ़ाते हैं, और अनुमान उपयोगकर्ता को दिखाई देने वाले परिणाम को ले जाते हैं।
कोई ईवेंट स्ट्रीम एक वास्तुशिल्प निर्णय तभी बन पाता है जब वह दोबारा आने, देर से आने और दोबारा चलाए जाने पर सुरक्षित हो।
अगले भाग में, हम देखेंगे कि जब सिस्टम चलते समय क्रैश हो जाता है तो क्या परिवर्तन होता है: स्थिरता, डुप्लिकेट, दूषित अनुमान और पुनर्प्राप्ति रणनीतियाँ।
What should remain with you?
If you remember only five things:
- A command requests behavior.
- An event is a fact that happened.
- A broker carries events to the right consumers.
- A projection reads the same fact in the shape each screen needs.
- Outbox prevents event loss because the broker and database do not share one ACID transaction.
Every separation in this chapter has a reason: idempotency is needed because a broker can redeliver; a projection is needed because querying an aggregate for every screen is expensive and the wrong abstraction.
FAQ
Frequently asked questions
डोमेन इवेंट क्या है?
भूतकाल में व्यक्त यह एक अपरिवर्तनीय तथ्य है जो व्यवसाय के क्षेत्र में घटित हुआ है।
ब्रोकर क्या है?
यह संचार परत है जो संदेश को कायम रखती है और इसे उपभोक्ताओं तक वितरित करती है।
क्या "इवेंट=कमांड" सही है?
आदेश इरादा है; घटना वास्तविक है.
इंजीनियरिंग सिद्धांत सीखे गए
- एक वितरित प्रणाली में, एक घटना एक कमांड नहीं है; यह एक स्थापित एवं अपरिवर्तनीय व्यावसायिक तथ्य है।
- कम से कम एक बार डिलीवरी के बराबर निष्क्रिय उपभोक्ता है; डुप्लिकेट संदेश एक डिज़ाइन इनपुट है, अपवाद नहीं।
- प्रक्षेपण पुनर्निर्माण योग्य, मापने योग्य होना चाहिए, और इसकी देरी को उत्पाद भाषा में परिभाषित किया जाना चाहिए।
जारी रखें पढ़ रहे हैं
जारी रखें पढ़ रहे हैं
श्रृंखला में अगला
उत्पादन में CQRS (कमांड क्वेरी रिस्पॉन्सिबिलिटी सेग्रीगेशन): संगति, त्रुटियाँ और पुनर्प्राप्ति रणनीतियाँ
CQRS उत्पादन परिवेश में सुरक्षित रूप से कैसे काम करता है? संगति अंतराल, डुप्लिकेट ईवेंट, अनुक्रम भ्रष्टाचार, प्रक्षेपण पुनर्प्राप्ति, पुनः प्रयास, डीएलक्यू…
श्रृंखला में अगला
CQRS (कमांड क्वेरी रिस्पॉन्सिबिलिटी सेग्रीगेशन) पाइपलाइन कैसे काम करती है? कमांड और क्वेरी फ़्लो का एनाटॉमी
CQRS अनुरोध पाइपलाइन क्या है? HTTP अनुरोध नियंत्रक, MediatR, पाइपलाइन व्यवहार, हैंडलर, आउटबॉक्स और रीड मॉडल के माध्यम से कैसे आगे बढ़ता है?
वही सिलसिला
सीआरयूडी (बनाएं, पढ़ें, अपडेट करें, हटाएं) से सीक्यूआरएस (कमांड क्वेरी रिस्पॉन्सिबिलिटी सेग्रीगेशन) तक: समस्या मॉडल है, कोड नहीं
CQRS क्या है, CRUD और CQRS में क्या अंतर है और CQRS का उपयोग कब किया जाना चाहिए? एक मार्गदर्शिका यह बताती है कि बड़ी प्रणालियों में एक ही मॉडल पर्याप्त…