प्रतिनिधि इंटरव्यू विषय

PostgreSQL बैकएंड साक्षात्कार: डेटा खोए बिना लॉजिकल रेप्लिकेशन का फ़ेलओवर कैसे करें?

बैकएंडकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक PostgreSQL प्राइमरी लॉजिकल रेप्लिकेशन के माध्यम से एक वेयरहाउस और एक सर्च सर्विस में ऑर्डर परिवर्तनों को स्ट्रीम करता है। जब उपभोक्ता पीछे हों, तब प्राइमरी विफल हो सकता है। नियोजित और अनियोजित फ़ेलओवर डिज़ाइन करें, बताएं कि स्टैंडबाय पर लॉजिकल स्लॉट कार्यभार संभाल सकते हैं यह कैसे सत्यापित करें, डुप्लिकेट या छूटी हुई LSN सीमाओं से कैसे बचें, और जब स्लॉट की निरंतरता सिद्ध न हो सके तो रिकवर कैसे करें।

प्रॉम्प्ट और लागू भूमिकाएँ

एक PostgreSQL प्राइमरी लॉजिकल रेप्लिकेशन के माध्यम से एक वेयरहाउस और एक सर्च सर्विस में ऑर्डर परिवर्तनों को स्ट्रीम करता है। जब उपभोक्ता पीछे हों, तब प्राइमरी विफल हो सकता है। नियोजित और अनियोजित फ़ेलओवर डिज़ाइन करें, बताएं कि स्टैंडबाय पर लॉजिकल स्लॉट कार्यभार संभाल सकते हैं यह कैसे सत्यापित करें, डुप्लिकेट या छूटी हुई LSN सीमाओं से कैसे बचें, और जब स्लॉट की निरंतरता सिद्ध न हो सके तो रिकवर कैसे करें।

यह बैकएंड, डेटाबेस-प्लेटफ़ॉर्म, डेटा-इन्फ्रास्ट्रक्चर और SRE साक्षात्कारों के लिए उपयुक्त है। PostgreSQL सब्सक्राइबर्स को गैर-PostgreSQL उपभोक्ताओं जैसे Debezium से अलग करें: पूर्व बिल्ट-इन फ़ेलओवर सेटिंग्स का उपयोग कर सकते हैं, जबकि बाद वाले को अभी भी कनेक्टर स्थिति, स्लॉट और समाधान (reconciliation) में स्वतंत्र साक्ष्य की आवश्यकता होती है। "स्टैंडबाय सिंक्रोनाइज़्ड है" यह साबित नहीं करता है कि प्रत्येक लॉजिकल उपभोक्ता निर्बाध रूप से जारी रह सकता है।

साक्षात्कारकर्ता क्या परीक्षण कर रहा है

एक मजबूत उत्तर सत्यापन योग्य इनवेरिएंट्स (invariants) बताता है: नए प्राइमरी पर लॉजिकल स्ट्रीम पीछे नहीं जानी चाहिए; एक उपभोक्ता एक पुष्ट स्थिति से फिर से शुरू होता है, जिसमें डुप्लिकेट की अनुमति है लेकिन मौन अंतराल (silent gaps) वर्जित हैं; और फ़ेलओवर स्लॉट सिंक्रोनाइज़ेशन और उपभोक्ता प्रगति पर निर्भर (gated) है। उम्मीदवार को नियोजित फ़ेलओवर, जहाँ राइट्स को रोका जा सकता है और उपभोक्ताओं को ड्रेन किया जा सकता है, को अनियोजित विफलता से अलग करना चाहिए, जहाँ एक बैकअप, पूर्ण स्नैपशॉट और समाधान ही एकमात्र सुरक्षित सुधार हो सकता है। स्टैंडबाय पर केवल DNS को इंगित करना स्लॉट, WAL प्रतिधारण या गैर-PostgreSQL उपभोक्ताओं को संबोधित नहीं करता है।

उत्तर देने से पहले स्पष्ट करने योग्य प्रश्न

  • उपभोक्ता क्या हैं? PostgreSQL सब्सक्राइबर्स, Debezium, वेयरहाउस लोडर्स और कस्टम डिकोडर्स के पास अलग-अलग प्रगति और रिकवरी इंटरफेस होते हैं।
  • क्या डुप्लिकेट स्वीकार्य हैं? एट-लीस्ट-वन्स (At-least-once) डिलीवरी आमतौर पर तब स्वीकार्य होती है जब लक्ष्य LSN, ट्रांजेक्शन ID, या एक इडेम्पोटेंसी (idempotency) कुंजी द्वारा डुप्लिकेट हटाते हैं; एक स्क्रिप्ट केवल दावे से एक्ज़ैक्टली-वन्स (exactly once) का वादा नहीं कर सकती है।
  • क्या यह नियोजित या आपदा फ़ेलओवर है? नियोजित स्विचिंग राइट्स को रोक सकती है और स्टैंडबाय की प्रतीक्षा कर सकती है; एक अनियोजित विफलता के बाद, अंतिम कमिटेड और उपभोक्ता-पुष्ट LSN अज्ञात हो सकता है।
  • क्या क्रॉस-टेबल ट्रांजेक्शन सीमाएं मायने रखती हैं? यदि डाउनस्ट्रीम को एक एटॉमिक ऑर्डर और ऑर्डर-लाइन दृश्य की आवश्यकता है, तो एकल-पंक्ति LSNs की तुलना करने के बजाय ट्रांजेक्शन सीमाओं का प्रचार करें।
  • कितना WAL बनाए रखा जा सकता है? एक पिछड़ा हुआ स्लॉट WAL क्लीनअप को रोकता है, जिससे प्राइमरी डिस्क समाप्त होने का जोखिम होता है; एक अमान्य स्लॉट एक अपूरणीय अंतर पैदा कर सकता है।
  • क्या उपभोक्ताओं को स्नैपशॉट से पुनर्गठित किया जा सकता है? यदि निरंतरता सिद्ध नहीं की जा सकती है, तो एक पूर्ण स्नैपशॉट, संस्करण समाधान, और एक डिग्रेडेशन या रखरखाव योजना तैयार करें।

30-सेकंड उत्तर फ्रेमवर्क

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

PostgreSQL 17 स्टैंडबाय पर फ़ेलओवर स्लॉट को एसिंक्रोनस रूप से सिंक्रोनाइज़ कर सकता है, लेकिन स्विच को यह जांचना चाहिए कि प्रत्येक स्लॉट मौजूद है, सिंक्रोनाइज़्ड है, गैर-अस्थायी है, और इसका कोई अमान्यकरण कारण नहीं है। Debezium और अन्य गैर-PostgreSQL उपभोक्ताओं को स्वतंत्र रूप से अपने स्लॉट और LSN को सत्यापित करना चाहिए। एक अनियोजित विफलता के बाद, यदि निरंतरता अज्ञात है, तो एक नया स्लॉट न बनाएं और जारी रखने का दिखावा न करें; एक विश्वसनीय बैकअप या स्नैपशॉट से पुनर्निर्माण करें और कुंजी, ट्रांजेक्शन और LSN द्वारा समाधान करें।"

चरण-दर-चरण गहन विश्लेषण

चरण 1: स्लॉट, LSNs और उपभोक्ता प्रगति को मॉडल करें

एक लॉजिकल रेप्लिकेशन स्लॉट एक परिवर्तन स्ट्रीम का प्रतिनिधित्व करता है जिसे स्रोत क्रम में फिर से चलाया जा सकता है। restart_lsn सबसे प्रारंभिक WAL स्थिति है जिसे अभी भी बनाए रखा जाना चाहिए; उपभोक्ता की स्वीकृत प्रगति को आमतौर पर confirmed_flush_lsn या कनेक्टर-विशिष्ट ऑफ़सेट द्वारा दर्शाया जाता है। वे विभिन्न प्रश्नों का उत्तर देते हैं: पहला WAL रिक्लेमेशन को नियंत्रित करता है, जबकि दूसरा बताता है कि उपभोक्ता ने कहाँ तक प्रोसेस किया है।

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

चरण 2: नियोजित फ़ेलओवर के लिए एक सत्यापन योग्य सुरक्षित बिंदु बनाएं

नियोजित फ़ेलओवर एक संक्षिप्त रीड-ओनली या ड्रेन विंडो का उपयोग कर सकता है। प्रत्येक उपभोक्ता के अंतिम सुरक्षित ऑफ़सेट को रिकॉर्ड करें, तब तक प्रतीक्षा करें जब तक कि स्टैंडबाय का भौतिक रीप्ले आवश्यक स्लॉट स्थिति को कवर न कर ले, और फिर जांचें कि स्टैंडबाय पर फ़ेलओवर स्लॉट उपयोग करने योग्य हैं। PostgreSQL को पुष्टि की आवश्यकता होती है कि स्लॉट सिंक्रोनाइज़्ड हैं; failover_ready का अर्थ है कि स्लॉट सिंक्रोनाइज़्ड है, गैर-अस्थायी है, और इसका कोई अमान्यकरण कारण नहीं है।

text
freeze_or_throttle_writes()
stop_consumers_after_recording_offsets()
wait_until(standby_replay_lsn >= required_slot_positions)
assert all(required_slots on standby are synced and valid)
promote(standby)
verify_slot_positions_are_monotonic()
restart_consumers_from_last_safe_offsets()
reconcile_sampled_rows_and_transactions()

एक PostgreSQL सब्सक्राइबर सब्सक्रिप्शन या स्लॉट फ़ेलओवर सेटिंग्स का उपयोग कर सकता है। एक Debezium कनेक्टर को अपने ऑफ़सेट को संरक्षित करना चाहिए, पुष्टि करनी चाहिए कि मेल खाने वाला स्लॉट नए प्राइमरी पर मौजूद है, और यह साबित करना चाहिए कि यह उसी LSN से जारी रह सकता है। एक स्क्रिप्ट का सफलता कोड उन स्थिति जांचों का विकल्प नहीं है।

चरण 3: अनियोजित विफलता और डुप्लिकेट डिलीवरी को संभालें

जब प्राइमरी गायब हो जाता है, तो स्टैंडबाय में पहले की WAL स्थिति हो सकती है, और एक उपभोक्ता को अपने ऑफ़सेट को स्थायी रूप से रिकॉर्ड किए बिना एक ईवेंट प्राप्त हो सकता है। एक सीमित ओवरलैप की अनुमति दें और स्रोत LSN, ट्रांजेक्शन ID, या एक डोमेन इडेम्पोटेंसी कुंजी द्वारा डाउनस्ट्रीम में डुप्लिकेट हटाएं। नए प्राइमरी का स्लॉट एक सिंक्रोनाइज़्ड स्थिति से आना चाहिए; यदि निरंतरता अज्ञात है, तो वर्तमान WAL स्थिति पर एक स्लॉट बनाने से छोड़े गए LSNs पुनर्प्राप्त नहीं हो सकते हैं।

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

चरण 4: स्लॉट अमान्यकरण और WAL वृद्धि को नियंत्रित करें

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

नवीनतम सुसंगत बैकअप या पूर्ण स्नैपशॉट से उपभोक्ता का पुनर्निर्माण करें, स्नैपशॉट स्थिति रिकॉर्ड करें, और उस स्थिति के बाद के परिवर्तनों का उपभोग करें। कुंजी संस्करण, ट्रांजेक्शन ID, डिलीट टॉम्बस्टोन (tombstone) और अपेक्षित गणनाओं द्वारा समाधान करें। समाधान पास होने तक उपभोक्ता को डिग्रेडेड रखें; "उपभोक्ता कनेक्ट हो गया" डेटा की पूर्णता नहीं है।

चरण 5: अभ्यास (drills) और मापों के साथ फ़ेलओवर सत्यापित करें

नियोजित राइट-फ्री स्विचिंग, एक पिछड़े हुए उपभोक्ता, विलंबित स्लॉट सिंक्रोनाइज़ेशन, अचानक प्राइमरी की हानि, डुप्लिकेट संदेश, पुराने प्राइमरी की आकस्मिक वापसी, स्लॉट अमान्यकरण, स्कीमा परिवर्तन और एक बड़े ट्रांजेक्शन का अभ्यास करें। प्राइमरी और स्टैंडबाय टाइमलाइन, स्लॉट स्थिति, restart_lsn, confirmed_flush_lsn, उपभोक्ता ऑफ़सेट, ट्रांजेक्शन सीमाएं और व्यावसायिक गणनाएं रिकॉर्ड करें।

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

उच्च-गुणवत्ता वाला नमूना उत्तर

"मैं पहले निरंतरता को परिभाषित करूँगा: नए प्राइमरी का स्लॉट उपभोक्ता की अंतिम सुरक्षित स्थिति को कवर करता है और स्रोत LSNs मोनोटोनिक रूप से बढ़ते हैं। डुप्लिकेट स्वीकार्य हैं, मूक अंतराल नहीं। प्रत्येक गैर-PostgreSQL उपभोक्ता को अपना स्लॉट मिलता है, और कनेक्टर ऑफ़सेट, स्लॉट स्थिति और व्यावसायिक समाधान एक साक्ष्य सेट बनाते हैं।

नियोजित फ़ेलओवर के लिए, मैं राइट्स को रोकता या थ्रॉटल करता हूँ, प्रत्येक उपभोक्ता ऑफ़सेट रिकॉर्ड करता हूँ, स्लॉट स्थिति को कवर करने के लिए स्टैंडबाय के भौतिक रीप्ले की प्रतीक्षा करता हूँ, और सत्यापित करता हूँ कि प्रत्येक फ़ेलओवर स्लॉट सिंक्रोनाइज़्ड, गैर-अस्थायी और मान्य है। मैं कनेक्टर्स को रोकता हूँ, स्टैंडबाय को प्रमोट करता हूँ, मोनोटोनिक स्थितियों को सत्यापित करता हूँ, और अंतिम सुरक्षित ऑफ़सेट से फिर से शुरू करता हूँ। PostgreSQL सब्सक्राइबर्स बिल्ट-इन फ़ेलओवर सेटिंग्स का उपयोग कर सकते हैं; Debezium उपभोक्ताओं को नए स्लॉट और LSN को स्वतंत्र रूप से सत्यापित करना होगा।

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

सामान्य गलतियाँ

  • केवल DNS या कनेक्शन स्ट्रिंग को स्विच करना → लॉजिकल स्लॉट और उपभोक्ता ऑफ़सेट स्वचालित रूप से निरंतर नहीं होते हैं → स्लॉट, LSN और उपभोक्ता स्थिति पर फ़ेलओवर को गेट करें।
  • भौतिक स्टैंडबाय सिंक को लॉजिकल-स्लॉट की तैयारी मानना → स्लॉट सिंक्रोनाइज़ेशन एसिंक्रोनस है और उपभोक्ताओं से पीछे रह सकता है → प्रत्येक स्लॉट की सिंक की गई, मान्य और रीप्ले स्थिति की जांच करें।
  • उपभोक्ताओं के बीच एक स्लॉट साझा करना → एकल-उपभोक्ता डिलीवरी चुपचाप दूसरों को अधूरा छोड़ देती है → प्रति स्वतंत्र उपभोक्ता एक स्लॉट या एक प्रसारण परत का उपयोग करें।
  • नए प्राइमरी पर एक नया स्लॉट बनाना → पहले से खोई हुई LSN सीमा को पुनर्प्राप्त नहीं किया जा सकता है → निरंतरता अज्ञात होने पर स्नैपशॉट से पुनर्निर्माण करें।
  • confirmed_flush_lsn को restart_lsn के रूप में मानना → एक उपभोक्ता की प्रगति है और दूसरा WAL प्रतिधारण को नियंत्रित करता है → उन्हें अलग से मॉनिटर करें और समझाएं।
  • फ़ेलओवर गुण के रूप में एक्ज़ैक्टली-वन्स का वादा करना → क्रैश विंडो अभी भी डुप्लिकेट बनाती हैं → एट-लीस्ट-वन्स प्लस इडेम्पोटेंट साइड इफेक्ट्स का उपयोग करें और डुप्लिकेट को मापें।
  • पुराने प्राइमरी को तुरंत फिर से जोड़ना → दोहरे लेखक (dual writers) भिन्न टाइमलाइन और LSNs बनाते हैं → इसे अलग करें, प्राधिकरण चुनें, और नई टाइमलाइन पर पुनर्निर्माण करें।
  • केवल डेटाबेस उपलब्धता का अभ्यास करना → स्लॉट अमान्यकरण, लंबे ट्रांजेक्शन और WAL वृद्धि डेटा जोखिम को उजागर करते हैं → उपभोक्ता अंतराल, स्लॉट बिल्डअप और बड़े ट्रांजेक्शन इंजेक्ट करें।
  • उपभोक्ता के कनेक्ट होने पर रिकवरी की घोषणा करना → कनेक्शन की सफलता यह साबित नहीं करती है कि पंक्तियाँ या विलोपन पूर्ण थे → कुंजियों, ट्रांजेक्शन सीमाओं और व्यावसायिक गणनाओं का समाधान करें।

अनुवर्ती प्रश्न और उत्तर

अनुवर्ती 1: क्या नियोजित फ़ेलओवर में राइट्स को रोकना आवश्यक है?

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

अनुवर्ती 2: एक गैर-PostgreSQL उपभोक्ता को कैसे पता चलता है कि नया स्लॉट निरंतर है?

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

अनुवर्ती 3: फ़ेलओवर के दौरान एक बड़े ट्रांजेक्शन का क्या होगा?

कमिटेड, अनकमिटेड और आंशिक रूप से डिकोड की गई स्थितियों में अंतर करें। यदि डाउनस्ट्रीम को ट्रांजेक्शन एटॉमिजिटी की आवश्यकता है, तो BEGIN/COMMIT सीमाओं का प्रचार करें और रिकवरी के बाद अपूर्ण अंशों को त्याग दें। यदि पंक्ति-स्तरीय अंतिम निरंतरता (eventual consistency) पर्याप्त है, तो मध्यवर्ती दृश्यता और रीप्ले नियमों को बताएं। अलग-अलग पंक्तियों के आगमन का क्रम एक पूर्ण ट्रांजेक्शन को साबित नहीं करता है।

अनुवर्ती 4: जब WAL डिस्क भर देता है तो क्या आप एक स्लॉट को हटा सकते हैं?

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

सार्वजनिक स्रोत

संबंधित प्रश्न