समस्या और दायरा
एक कंपनी के पास 20 PostgreSQL OLTP डेटाबेस, सिंक्रोनाइज़ करने के लिए 200 टेबल और 8 TB मौजूदा डेटा है। सोर्स से औसतन 20,000 कमिटेड रो बदलाव प्रति सेकंड और पीक पर 60,000 बदलाव जनरेट होते हैं। एक एन्कोडेड बदलाव औसतन लगभग 1 KB का होता है। डेटा को एक एनालिटिकल वेयरहाउस या लेकहाउस तक पहुंचना चाहिए, जिसमें सोर्स ट्रांज़ैक्शन कमिट से लेकर क्वेरी करने योग्य क्यूरेटेड डेटा तक p99 लेटेंसी दो मिनट से कम होनी चाहिए। इनिशियल सिंक्रोनाइज़ेशन एप्लिकेशन राइट्स को रोके बिना 72 घंटों के भीतर पूरा होना चाहिए, और स्नैपशॉट प्लस CDC वर्कलोड के कारण सोर्स राइट p99 में 5% से कम रिग्रेशन होना चाहिए।
पाइपलाइन को इंसर्ट, अपडेट, डिलीट और प्राइमरी-की वैल्यू में बदलाव को हैंडल करना होगा। इसे एक सोर्स के भीतर एक रो के लिए बदलाव के क्रम (ऑर्डर) को बनाए रखना चाहिए, एट-लीस्ट-वन्स डिलीवरी का उपयोग करना चाहिए, टेबल या प्राइमरी-की रेंज के अनुसार स्कीमा इवोल्यूशन और रीप्ले का समर्थन करना चाहिए, सोर्स और सिंक विफलताओं से उबरना (रिकवर) चाहिए, और ऐसा रिकॉन्सिलिएशन प्रदान करना चाहिए जो सटीकता (करेक्टनेस) को साबित कर सके। ड्यूरेबल चेंज स्ट्रीम सात दिनों के रॉ इवेंट्स को बनाए रखती है, जबकि कम लागत वाला ऑब्जेक्ट स्टोर लंबे समय का इतिहास रखता है। डेटाबेस की संख्या, थ्रूपुट, आकार, लेटेंसी और रिसोर्स सीमाएं इंटरव्यू के अनुमान हैं, किसी प्रोडक्ट के परफॉर्मेंस वादे नहीं।
यद्यपि डिज़ाइन में एक ब्रोकर और कई कंपोनेंट्स शामिल हैं, मुख्य कौशल डेटा इंजीनियरिंग का है: बिना किसी गैप के एक स्टोर किए गए स्नैपशॉट को अनबाउन्ड चेंज स्ट्रीम से जोड़ना, रिकवरेबल पोज़ीशन और इडेम्पोटेंसी सीमाओं को परिभाषित करना, और यह साबित करना कि डेस्टिनेशन में न तो डेटा छूट रहा है और न ही वह साइलेंटली गलत है।
इंटरव्यूअर्स क्या मूल्यांकन करते हैं
पहला संकेत कंपोनेंट्स बनाने से पहले शुद्धता (करेक्टनेस) को परिभाषित करना है। एक कमजोर उत्तर "Debezium प्लस Kafka" से शुरू होता है। एक मजबूत उत्तर इनवेरिएंट्स बताता है: कमिट किए गए बदलाव गायब नहीं हो सकते, एक रो को सोर्स ऑर्डर में कन्वर्ज होना चाहिए, रीप्ले किए गए इवेंट्स अंतिम स्थिति को नहीं बदल सकते, डिलीट टार्गेट तक पहुंचने चाहिए, स्नैपशॉट-टू-स्ट्रीम बाउंड्री में कोई गैप नहीं हो सकता, और एक अनिश्चित रिकवरी पोज़ीशन को चुपचाप जारी रखने के बजाय फ़ेल क्लोज़ होना चाहिए।
दूसरा संकेत यह समझना है कि इनिशियल स्नैपशॉट का मतलब "सभी टेबल एक्सपोर्ट करें, फिर CDC इनेबल करें" नहीं है। 8 TB एक्सपोर्ट के दौरान राइट्स जारी रहते हैं। यदि WAL कैप्चर एक्सपोर्ट के बाद ही शुरू होता है, तो बीच के बदलाव पहले ही गायब हो सकते हैं। एक विश्वसनीय डिज़ाइन एक सुसंगत (कंसिस्टेंट) स्नैपशॉट प्राप्त करने से पहले या उसके दौरान एक रिकवरेबल लॉग पोज़ीशन और रिटेंशन मैकेनिज्म स्थापित करता है, फिर मैचिंग पोज़ीशन से कमिटेड बदलावों को स्ट्रीम करता है। एक कनेक्टर इस प्रक्रिया को एनकैप्सुलेट कर सकता है, लेकिन उम्मीदवार को अभी भी यह समझाना होगा कि हैंडऑफ़ में कोई गैप क्यों नहीं है।
तीसरा संकेत सिंक के माध्यम से एट-लीस्ट-वन्स डिलीवरी को बनाए रखना है। एक कनेक्टर इवेंट को ड्यूरेबली एमिट करने के बाद लेकिन अपने सोर्स ऑफ़सेट को रिकॉर्ड करने से पहले क्रैश हो सकता है। एक वेयरहाउस बैच कमिट हो सकता है जबकि उसका एकनॉलेजमेंट खो जाता है। "ब्रोकर में एग्जैक्टली वन्स" स्वचालित रूप से बाहरी वेयरहाउस को शामिल नहीं करता है। मजबूत उत्तर प्रत्येक इवेंट के साथ सोर्स आइडेंटिटी, सोर्स पोज़ीशन और ट्रांज़ैक्शन ऑर्डर जोड़ते हैं, फिर किसी इवेंट को केवल तभी लागू करते हैं जब उसका वर्शन उस रो के लिए पहले से रिकॉर्ड किए गए वर्शन से नया हो।
चौथा संकेत PostgreSQL रेप्लिकेशन स्लॉट्स के दोनों पहलुओं के जोखिम को पहचानना है। एक स्लॉट कनेक्टर को LSN से फिर से शुरू करने की अनुमति देता है, लेकिन जब कनेक्टर पीछे छूट जाता है तो यह WAL को भी रोक कर (रिटेन) रखता है। रिटेंड-बाइट और डिस्क-हेडरूम अलर्ट के बिना, सिंक आउटेज अंततः सोर्स स्टोरेज को भर सकता है। यदि कोई स्लॉट ड्रॉप कर दिया जाता है और फिर से बनाया जाता है, तो नया स्लॉट पुरानी पोज़ीशन को पुन: उत्पन्न नहीं कर सकता है। पाइपलाइन को "अब से" जारी रखने और यह दावा करने के बजाय कि कुछ भी नहीं खोया था, रुकना, रिकॉन्सिल करना या फिर से स्नैपशॉट लेना चाहिए।
अंत में, उत्तर में वास्तविक डेटा सिमेंटिक्स शामिल होने चाहिए। एक बिज़नेस डिलीट इवेंट लॉग कॉम्पेक्शन के लिए उपयोग किए जाने वाले टॉम्बस्टोन से अलग होता है। प्राइमरी-की वैल्यू अपडेट आमतौर पर पुरानी की (key) के लिए डिलीट और नई की के लिए क्रिएट के रूप में दिखाई देता है। अलग-अलग डेटाबेस से LSNs की तुलना नहीं की जा सकती। यदि कंज्यूमर्स को मल्टी-रो ट्रांज़ैक्शन में प्रत्येक रो के लिए एटॉमिक विजिबिलिटी की आवश्यकता होती है, तो डिज़ाइन को ट्रांज़ैक्शन-बाउंड्री मेटाडेटा का उपयोग करना चाहिए और अतिरिक्त बफरिंग, लेटेंसी और रिकवरी जटिलता को स्वीकार करना चाहिए।
उत्तर देने से पहले स्पष्ट करने योग्य प्रश्न
- क्या डेस्टिनेशन को वर्तमान स्थिति (करंट स्टेट), पूर्ण परिवर्तन इतिहास (फुल चेंज हिस्ट्री), या दोनों की आवश्यकता है? वर्तमान स्थिति प्राइमरी-की MERGE ऑपरेशन्स के अनुकूल है। ऑडिट और रीप्ले के लिए एक इम्यूटेबल रॉ चेंज लेयर की भी आवश्यकता होती है। केवल अंतिम स्थिति इतिहास का पुनर्निर्माण नहीं कर सकती।
- दो मिनट की लेटेंसी क्लॉक कहाँ से शुरू और समाप्त होती है? यह समस्या सोर्स कमिट से लेकर क्वेरी करने योग्य क्यूरेटेड डेटा तक मापी जाती है। ब्रोकर में रॉ इवेंट दर्ज होने पर समाप्त होने वाली आवश्यकता बहुत आसान होती है।
- क्या मल्टी-टेबल ट्रांज़ैक्शन को एटॉमिक रूप से दिखाई देना चाहिए? यहाँ डिफ़ॉल्ट वेयरहाउस में संक्षिप्त आंशिक विजिबिलिटी के साथ प्रति-रो ऑर्डरिंग है। एक वित्तीय कंज्यूमर जिसे पूरे ट्रांज़ैक्शन की एटॉमिक्सिटी की आवश्यकता होती है, उसे BEGIN/END असेंबली की आवश्यकता होती है।
- क्या प्रत्येक टेबल में एक स्थिर (स्टेबल) प्राइमरी की है? इसके बिना, UPDATE और DELETE इवेंट्स को ढूंढना और डुप्लीकेट हटाना (डीडुप्लिकेट करना) कठिन होता है। एक बिज़नेस की जोड़ें या पूर्ण-रो आइडेंटिटी, सरोगेट की और अधिक स्टोरेज लागत को स्पष्ट रूप से स्वीकार करें।
- क्या सोर्स फ़ेलओवर लॉजिकल रेप्लिकेशन स्लॉट्स को सुरक्षित रखता है? यदि नहीं, तो रिकवरी के लिए एक नियंत्रित राइट पॉज़, अंतिम-LSN वेरिफिकेशन, स्लॉट रीक्रिएशन और रिकॉन्सिलिएशन की आवश्यकता होती है। प्राइमरी फ़ेलओवर को एक साधारण रीकनेक्ट के रूप में नहीं माना जा सकता।
- कौन से स्कीमा परिवर्तन स्वचालित रूप से पास हो सकते हैं? यह डिज़ाइन स्वचालित रूप से संगत परिवर्तनों को स्वीकार करता है जैसे कि एक जोड़ी गई नलेबल कॉलम। ड्रॉप्स, रीनेम्स, नैरोइंग टाइप परिवर्तन और प्राइमरी-की परिवर्तन नियंत्रित माइग्रेशन का उपयोग करते हैं।
- 72 घंटे की स्नैपशॉट समय सीमा या 5% सोर्स बजट में से कौन सा अधिक कठिन है? 72 घंटों में 8 TB पढ़ने के लिए लगभग 30.9 MB/s के कुल प्रभावी थ्रूपुट की आवश्यकता होती है। यदि लोड टेस्ट से पता चलता है कि यह सोर्स बजट को तोड़ता है, तो समय सीमा बढ़ाएं, सिमेंटिक रूप से मान्य रेप्लिकेट का उपयोग करें, या चरणों में दायरे को कम करें।
- ऑनलाइन स्ट्रीम को डेस्टिनेशन आउटेज को कब तक सहन करना चाहिए? यह डिज़ाइन ऑनलाइन 30 मिनट के पीक आउटेज को कवर करता है। सात-दिवसीय ड्यूरेबल स्ट्रीम और ऑब्जेक्ट आर्काइव लंबे रीप्ले को संभालते हैं।
30-सेकंड का उत्तर
"मैं पहले शुद्धता को परिभाषित करूँगा: स्नैपशॉट और स्ट्रीम में कोई गैप नहीं है, एक रो सोर्स पोज़ीशन द्वारा कन्वर्ज होती है, रीप्ले सुरक्षित है, डिलीट प्रोपेगेट होते हैं, और गायब रेप्लिकेशन-स्लॉट इतिहास फ़ेल क्लोज़ हो जाता है। प्रत्येक PostgreSQL सोर्स WAL पर लॉजिकल डिकोडिंग का उपयोग करता है, एक कंसिस्टेंट स्नैपशॉट लेता है, और संबंधित LSN से फिर से शुरू होता है। इवेंट्स को सोर्स, टेबल और प्राइमरी की द्वारा एक ड्यूरेबल स्ट्रीम में विभाजित (पार्टिशन) किया जाता है। रॉ लेयर इम्यूटेबल रहती है, जबकि क्यूरेटेड सिंक प्राइमरी की और सोर्स वर्शन द्वारा इडेम्पोटेंट MERGE ऑपरेशन्स करता है। एप्लिकेशन से पहले स्कीमा कम्पैटिबिलिटी की जाँच की जाती है, और डिलीट और की परिवर्तन स्पष्ट होते हैं। मैं सेगमेंटेड फ्रेशनेस, LSN लैग, रिटेंड WAL, स्नैपशॉट प्रोग्रेस और रिकॉन्सिलिएशन अंतरों की निगरानी करूँगा, फिर कनेक्टर क्रैश, स्लॉट लॉस, स्कीमा परिवर्तन और सिंक आउटेज को इंजेक्ट करूँगा।"
स्टेप-बाय-स्टेप डीप डाइव
स्टेप 1: बफर, स्नैपशॉट और रिकवरी बजट का आकार निर्धारित करें
औसत लोड है:
20,000 events/s × 1 KB ≈ 20 MB/s
20,000 × 86,400 = 1,728,000,000 events/day
20 MB/s × 86,400 ≈ 1.728 TB/dayपीक इनग्रेस लगभग 60 MB/s है। यदि डेस्टिनेशन पीक पर 30 मिनट के लिए रुकता है, तो रॉ बैकलॉग लगभग है:
60 MB/s × 1,800 seconds = 108 GBऔसत दर पर सात दिन रेप्लिकेशन, इंडेक्स और एन्कोडिंग ओवरहेड से पहले लगभग 12.096 TB रॉ डेटा होता है। ब्रोकर, ऑब्जेक्ट स्टोर और नेटवर्क को केवल 20 MB/s औसत के लिए नहीं, बल्कि पीक ट्रैफ़िक और कैच-अप के लिए आकार दें। यदि रिकवर किया गया कंज्यूमर केवल लाइव इनपुट दर के बराबर हो सकता है, तो यह 108 GB बैकलॉग को कभी नहीं हटा पाएगा; डिज़ाइन को अतिरिक्त कंजम्पशन क्षमता या क्यूरेटेड-लेयर लेटेंसी में अस्थायी ढील की आवश्यकता है।
72 घंटों में 8 TB स्नैपशॉट पूरा करने के लिए कम से कम आवश्यकता है:
8 TB ÷ 72 hours ≈ 30.9 MB/sयह एक निचली सीमा है जिसमें स्कैन प्रवर्धन (एम्प्लीफिकेशन), सीरियलाइज़ेशन, नेटवर्क पुनः प्रयास और टार्गेट राइट्स शामिल नहीं हैं। प्रोडक्शन-आकार के डेटा पर चंक्ड स्नैपशॉट का बेंचमार्क करें, फिर सोर्स I/O, कैश व्यवहार, रेप्लिकेशन लैग और p99 द्वारा दर सीमित (रेट-लिमिट) करें। यदि समय सीमा 5% सोर्स बजट के साथ टकराती है, तो OLTP को अत्यधिक प्रभावित करने के बजाय समय सीमा या सोर्स पाथ को बदलें।
स्टेप 2: प्रत्येक कंपोनेंट को शुद्धता या क्षमता की आवश्यकता को पूरा करने वाला बनाएं
मुख्य डेटा प्रवाह है:
PostgreSQL WAL / logical slot
→ source connector
→ durable change stream keyed by source + table + primary key
→ immutable raw archive
→ schema validation and light normalization
→ sink staging tables
→ idempotent MERGE / DELETE into curated tables
→ warehouse and lakehouse consumersप्रत्येक सोर्स डेटाबेस को उसका अपना सोर्स आइडेंटिफ़ायर, कनेक्टर और रेप्लिकेशन स्लॉट दें ताकि एक विफलता डोमेन सभी सोर्स को न रोके। ड्यूरेबल स्ट्रीम बर्स्ट को अवशोषित करती है, कंज्यूमर्स को अलग करती है, और अल्पकालिक रीप्ले का समर्थन करती है। ऑब्जेक्ट स्टोरेज लंबे इतिहास को बनाए रखता है। CDC प्रोसेसिंग लेयर को स्कीमा वैलिडेशन, नॉर्मलाइज़ेशन और रूटिंग तक सीमित रखें; मुख्य पाथ में एक गैर-रीप्ले करने योग्य बाहरी लुकअप रिकवरी को कठिन बनाता है। कुशल कॉलमर राइट्स के साथ दो मिनट के SLA को संतुलित करने के लिए स्टेजिंग टेबल और छोटे एटॉमिक MERGE बैचों के माध्यम से वेयरहाउस में लिखें।
पार्टिशन की के रूप में (source_id, table_id, primary_key) के एक स्थिर एन्कोडिंग का उपयोग करें ताकि एक रो के परिवर्तन एक ऑर्डर्ड पार्टिशन तक पहुँचें। यह ग्लोबल ऑर्डर प्रदान नहीं करता है, और ग्लोबल ऑर्डर अनावश्यक है। 20 सोर्स डेटाबेस में अलग-अलग LSN सीक्वेंस होते हैं जिनके संख्यात्मक मानों का कोई क्रॉस-सोर्स अर्थ नहीं होता है।
स्टेप 3: राइट-ऑनलाइन इनिशियल स्नैपशॉट निष्पादित करें
तार्किक क्रम है:
- एक लॉजिकल रेप्लिकेशन स्लॉट स्थापित करें ताकि कनेक्टर द्वारा इसका उपभोग करने से पहले आवश्यक WAL को रीक्लेम न किया जा सके।
- एक कंसिस्टेंट स्नैपशॉट और इसकी संबंधित सोर्स-लॉग पोज़ीशन प्राप्त करें।
- टेबल और प्राइमरी-की चंक्स में स्नैपशॉट पढ़ें, वर्तमान पंक्तियों को
READइवेंट्स के रूप में एमिट करें। - स्नैपशॉट से जुड़ी पोज़ीशन से कमिटेड INSERT, UPDATE, और DELETE रिकॉर्ड स्ट्रीम करें।
- सिंक को सोर्स वर्शन द्वारा कन्वर्ज होने दें, जिससे रिकवरी के दौरान बाउंड्री रीप्ले की अनुमति मिलती है लेकिन कभी भी मिसिंग इंटरवल की अनुमति नहीं मिलती है।
एक कनेक्टर पूर्ण कंसिस्टेंट स्नैपशॉट या इंक्रीमेंटल स्नैपशॉट विंडो को लागू कर सकता है। उत्तर में "एक LSN रिकॉर्ड करें, फिर सामान्य SELECT स्टेटमेंट चलाएं" प्रोटोकॉल का आविष्कार नहीं किया जाना चाहिए क्योंकि आइसोलेशन, लंबे ट्रांज़ैक्शन और समवर्ती (कन्करेंट) राइट्स इसे भ्रामक रूप से जटिल बनाते हैं। सत्यापित कनेक्टर सिमेंटिक्स पर भरोसा करें और एक प्राइमरी की का परीक्षण करें जो बार-बार अपडेट, डिलीट और रीक्रिएट की जाती है जब उसका स्नैपशॉट चंक चल रहा हो।
प्राइमरी-की रेंज द्वारा चंक करें और प्रगति को बनाए रखें (परसिस्ट करें)। छोटे चंक लंबे ट्रांज़ैक्शन, कैश डिस्टर्बेंस और विफलता के बाद दोबारा काम करने को कम करते हैं; अत्यधिक छोटे चंक क्वेरी और शेड्यूलिंग ओवरहेड जोड़ते हैं। प्रत्येक सोर्स को स्वतंत्र रूप से रेट-लिमिट करें, पहले छोटी टेबल के साथ एंड-टू-एंड विश्वास स्थापित करें, फिर बड़ी टेबल को प्रोसेस करें। स्नैपशॉट के दौरान कनेक्टर को WAL को ड्रेन करते रहना चाहिए अन्यथा रिटेंड WAL बढ़ जाएगा। यदि चुना गया कनेक्टर इंक्रीमेंटल स्नैपशॉट के दौरान स्कीमा परिवर्तनों का समर्थन नहीं करता है, तो उस टेबल के लिए DDL फ्रीज करें या उसके स्नैपशॉट को रोकें।
स्टेप 4: इवेंट, ऑर्डरिंग और इडेम्पोटेंट एप्लिकेशन को परिभाषित करें
एक नॉर्मलाइज़्ड इवेंट में कम से कम शामिल हैं:
ChangeEvent {
event_id
source_id
table_id
primary_key
operation // READ | CREATE | UPDATE | DELETE
before
after
source_lsn
transaction_id
transaction_order
source_commit_time
schema_version
captured_at
}एक सोर्स के भीतर, source_lsn प्लस ट्रांज़ैक्शन ऑर्डर इवेंट ऑर्डर स्थापित करता है। वर्शन की में source_id शामिल होना चाहिए क्योंकि विभिन्न डेटाबेस के LSNs एक कोऑर्डिनेट सिस्टम शेयर नहीं करते हैं। प्रत्येक (source_id, table_id, primary_key) के लिए, टार्गेट अंतिम लागू सोर्स वर्शन को स्टोर करता है। सिंक रो को बदले बिना एक समान या पुराने वर्शन को एकनॉलेज करता है। एक नया वर्शन एक टार्गेट ट्रांज़ैक्शन में बिज़नेस रो और लागू वर्शन दोनों को अपडेट करता है।
यह मुख्य एट-लीस्ट-वन्स विफलता विंडो को प्रबंधनीय बनाता है:
- इवेंट ड्यूरेबल स्ट्रीम तक पहुँचता है लेकिन उसका सोर्स ऑफ़सेट रिकॉर्ड नहीं होता है: रिकवरी इसे फिर से एमिट करती है, और सिंक समान वर्शन को अनदेखा करता है।
- टार्गेट MERGE कमिट होता है लेकिन एकनॉलेजमेंट खो जाता है: बैच फिर से प्ले होता है और उसी स्थिति में कन्वर्ज हो जाता है।
- बैच के बीच में कंज्यूमर क्रैश हो जाता है: कमिटेड पंक्तियाँ सुरक्षित रूप से रीप्ले होती हैं और अनकमिटेड पंक्तियों को फिर से प्रोसेस किया जाता है।
यदि डेस्टिनेशन को मल्टी-रो ट्रांज़ैक्शन एटॉमिक्सिटी की आवश्यकता होती है, तो ट्रांज़ैक्शन-बाउंड्री मेटाडेटा को सक्षम करें और END तक transaction_id द्वारा बफ़र करें, फिर पूरे ट्रांज़ैक्शन को एक साथ कमिट करें। बड़े ट्रांज़ैक्शन अधिक मेमोरी का उपभोग करते हैं और टेल लेटेंसी बढ़ाते हैं, और टाइमआउट या रिकवरी लॉजिक को यह निर्धारित करना होगा कि ट्रांज़ैक्शन पूरा हुआ है या नहीं। एक सामान्य एनालिटिकल वेयरहाउस जिसे रो-लेवल इवेंचुअल कंसिस्टेंसी की आवश्यकता होती है, उसे वास्तविक आवश्यकता के बिना इस जटिलता को स्वीकार नहीं करना चाहिए।
स्टेप 5: डिलीट, की परिवर्तन और स्कीमा इवोल्यूशन को सही ढंग से संभालें
एक DELETE इवेंट में क्यूरेटेड लेयर के लिए रो को हार्ड-डिलीट करने, is_deleted सेट करने या इतिहास को संरक्षित करने के लिए पर्याप्त की-जानकारी होनी चाहिए। एक डिलीट के बाद आने वाला टॉम्बस्टोन मुख्य रूप से लॉग कॉम्पेक्शन का समर्थन करता है। यह बिज़नेस डिलीट इवेंट को प्रतिस्थापित नहीं कर सकता है, और मिडलवेयर को टार्गेट तक पहुंचने से पहले डिलीट को नहीं हटाना चाहिए।
जब कोई प्राइमरी-की वैल्यू बदलती है, तो सामान्य CDC सिमेंटिक्स पुरानी की के लिए डिलीट और नई की के लिए क्रिएट एमिट करते हैं। सिंक को दोनों को लागू करना होगा अन्यथा पुरानी की घोस्ट रो के रूप में बनी रहती है। प्राइमरी-की परिभाषा को बदलना वैल्यू बदलने की तुलना में अधिक जोखिम भरा है। रीड-ओनली या राइट-पॉज़ विंडो का उपयोग करें, कनेक्टर को ड्रेन करें, स्कीमा को अपडेट करें, और फिर फिर से शुरू करें क्योंकि ट्रांज़िशन के दौरान इवेंट-की शेप असंगत हो सकता है।
एक स्पष्ट कम्पैटिबिलिटी नीति का उपयोग करें:
- जोड़ी गई नलेबल कॉलम: एक नया वर्शन रजिस्टर करें, पुराने कंज्यूमर्स को अज्ञात फ़ील्ड को अनदेखा करने दें, राइट्स सक्षम करने से पहले क्यूरेटेड टेबल का विस्तार करें।
- ड्रॉप या रीनेम की गई कॉलम: नए फ़ील्ड को पेश करें और पॉप्युलेट करें, प्रत्येक कंज्यूमर को माइग्रेट करें, फिर पुराने फ़ील्ड को हटा दें।
- वाइड किया गया टाइप: टार्गेट कम्पैटिबिलिटी जांच के बाद अपग्रेड करें। नैरो किए गए टाइप या सिमेंटिक परिवर्तन असंगत इवेंट्स को क्वारंटाइन करते हैं।
- प्राइमरी-की परिवर्तन: साइलेंट ऑटोमैटिक इवोल्यूशन के बजाय एक अलग माइग्रेशन के रूप में हैंडल करें।
एक असंगत इवेंट क्वारंटाइन में प्रवेश करता है और एक अलर्ट उठाता है। मुख्य ऑफ़सेट केवल तभी आगे बढ़ सकता है जब इवेंट ड्यूरेबली स्टोर हो, रीप्ले करने योग्य हो, और एक स्पष्ट रेमेडिएशन ओनर सौंपा गया हो। खराब स्कीमा को चुपचाप छोड़ना एक अदृश्य डेटा होल बनाता है।
स्टेप 6: रिकवरी, रीप्ले और रिकॉन्सिलिएशन को सामान्य पाथ मानें
कनेक्टर रिकवरी के लिए एक परसिस्टेड ऑफ़सेट और एक रेप्लिकेशन स्लॉट दोनों की आवश्यकता होती है जिसमें अभी भी संबंधित इतिहास शामिल हो। restart_lsn, confirmed_flush_lsn, वर्तमान WAL पोज़ीशन, रिटेंड बाइट्स, वृद्धि दर और डिस्क समाप्त होने के समय की निगरानी करें। एक डेस्टिनेशन आउटेज को सोर्स पर अनबाउन्ड WAL को बनाए रखने के लिए लंबे समय तक कनेक्टर एकनॉलेजमेंट को रोकने के बजाय ड्यूरेबल स्ट्रीम में जमा होना चाहिए।
यदि स्लॉट गायब है, स्टोर किया गया ऑफ़सेट स्लॉट की उपलब्ध पोज़ीशन से पीछे है, या आवश्यक WAL गायब हो गया है, तो फ़ेल क्लोज़ करें। उस सोर्स के लिए क्यूरेटेड पब्लिकेशन बंद करें, अंतिम विश्वसनीय पोज़ीशन रिकॉर्ड करें, प्रभावित टेबल का फिर से स्नैपशॉट लें, और रेंज द्वारा रिकॉन्सिल करें। एक नया बनाया गया स्लॉट केवल अपने निर्माण के बाद के परिवर्तनों को कैप्चर करता है और यह साबित नहीं कर सकता कि पिछला अंतराल पूर्ण है।
रीप्ले का अपना replay_job_id, टेबल और प्राइमरी-की स्कोप, और सोर्स-टाइम बाउंड्री होती है। यह इम्यूटेबल रॉ लेयर को स्टेजिंग में पढ़ता है। लाइव और रीप्ले डेटा एक ही सोर्स-वर्शन MERGE नियम का उपयोग करते हैं ताकि एक पुराना बैकफ़िल नई स्थिति को ओवरराइट न कर सके। जब ट्रांसफ़ॉर्मेशन लॉजिक बदलता है, तो पहले एक नया क्यूरेटेड वर्शन या शैडो टेबल बनाएं; तुरंत प्रोडक्शन को ओवरराइट करने की तुलना में तुलना करना और रोलबैक करना अधिक सुरक्षित है।
रिकॉन्सिलिएशन में कम से कम चार लेयर्स शामिल हैं:
- सोर्स कमिट पोज़ीशन से लेकर कनेक्टर, ड्यूरेबल स्ट्रीम और टार्गेट अप्लाइड पोज़ीशन तक निरंतरता (कंटिन्यूटी)।
- टेबल, तिथि और प्राइमरी-की बकेट द्वारा रो काउंट, डिलीट काउंट और चेकसम।
- सोर्स की वर्तमान स्थिति और डेस्टिनेशन की नवीनतम स्थिति के बीच सैंपल किए गए प्राइमरी-की कम्पेरिज़न।
- आवधिक पहचाने जाने योग्य कैनरी ट्रांज़ैक्शन जो SLA के भीतर INSERT, UPDATE, और DELETE विजिबिलिटी को सत्यापित करते हैं।
एंड-टू-एंड लेटेंसी को सोर्स कमिट से कैप्चर, कैप्चर से स्ट्रीम, स्ट्रीम से स्टेजिंग, और स्टेजिंग से क्यूरेटेड में विभाजित करें। प्रति सोर्स इवेंट दर, LSN लैग, रिटेंड स्लॉट WAL, स्नैपशॉट चंक प्रोग्रेस, डुप्लिकेट या पुराने वर्शन, स्कीमा क्वारंटाइन, टार्गेट MERGE विफलताएं, रिकॉन्सिलिएशन डेल्टा, और अनुमानित कैच-अप समय की भी निगरानी करें।
स्टेप 7: विकल्पों की सीमाओं की व्याख्या करें
updated_at द्वारा पोलिंग कम-राइट वाली टेबल के लिए सरल है जिसमें मिनट-स्तरीय फ्रेशनेस और स्वीकार्य रीस्कैन हैं। यह क्वेरी लोड जोड़ता है, आसानी से हार्ड डिलीट को मिस कर देता है, और फिर भी समान टाइमस्टैम्प और क्लॉक प्रिसिजन को संभालना पड़ता है। ट्रिगर डिलीट को ऑडिट टेबल में लिख सकते हैं, लेकिन वे सोर्स राइट पाथ में काम और ऑपरेशनल कपलिंग जोड़ते हैं। इस समस्या में व्यस्त OLTP वर्कलोड के लिए लॉग-आधारित CDC बेहतर डिफ़ॉल्ट है।
आउटबॉक्स पैटर्न एक अलग समस्या को हल करता है: एक सर्विस एक डेटाबेस ट्रांज़ैक्शन में बिज़नेस स्टेट और एक डोमेन इवेंट लिखती है, जिससे एक सफल डेटाबेस कमिट के बाद विफल मैसेज सेंड से बचा जा सकता है। यह चयनित बिज़नेस इवेंट्स के लिए उपयुक्त है। यह 200 टेबल के लिए जेनेरिक रो-लेवल सिंक्रोनाइज़ेशन को स्वचालित रूप से प्रतिस्थापित नहीं करता है। दोनों सह-अस्तित्व में रह सकते हैं: सर्विस इंटीग्रेशन आउटबॉक्स का उपभोग करता है, जबकि एनालिटिक्स और ऑडिट CDC का उपभोग करते हैं।
मजबूत नमूना उत्तर
"मैं गारंटियों के साथ शुरुआत करूँगा। प्रत्येक कमिटेड परिवर्तन जो अभी भी WAL या ड्यूरेबल स्ट्रीम में मौजूद है, रिकवरेबल होना चाहिए। एक रो सोर्स पोज़ीशन द्वारा कन्वर्ज होती है, रीप्ले उसकी अंतिम स्थिति को नहीं बदलता है, और डिलीट टार्गेट तक पहुँचते हैं। यदि रेप्लिकेशन स्लॉट और ऐतिहासिक पोज़ीशन अब बरकरार नहीं हैं, तो पब्लिकेशन रुक जाता है और प्रभावित डेटा का फिर से स्नैपशॉट लिया जाता है; कनेक्टर चुपचाप सबसे नई पोज़ीशन पर पुनः आरंभ नहीं हो सकता है।
औसत लोड पर, इनग्रेस लगभग 20 MB/s, 1.728 बिलियन इवेंट्स और 1.728 TB प्रति दिन है। पीक 60 MB/s है, इसलिए 30 मिनट का टार्गेट आउटेज लगभग 108 GB का बैकलॉग बनाता है। सात दिनों का रॉ रिटेंशन लगभग 12.096 TB है। 8 TB स्नैपशॉट को 72 घंटों के भीतर पूरा करने के लिए कम से कम 30.9 MB/s प्रभावी रीडिंग की आवश्यकता होती है, इसलिए मैं इसे बेंचमार्क करूँगा और प्रत्येक सोर्स को p99, I/O और रिटेंड WAL द्वारा रेट-लिमिट करूँगा।
प्रत्येक PostgreSQL सोर्स को एक स्वतंत्र लॉजिकल स्लॉट और कनेक्टर मिलता है। कनेक्टर एक कंसिस्टेंट स्नैपशॉट लेता है और फिर संबंधित LSN से कमिटेड परिवर्तनों को फिर से शुरू करता है। इवेंट्स को सोर्स, टेबल और प्राइमरी की द्वारा एक ड्यूरेबल स्ट्रीम में विभाजित किया जाता है और एक इम्यूटेबल रॉ लेयर में कॉपी किया जाता है। लाइट प्रोसेसिंग स्कीमा को मान्य करती है और एन्वेलप को सामान्य (नॉर्मलाइज़) करती है। वेयरहाउस स्टेजिंग टेबल लोड करता है, फिर प्राइमरी की और सोर्स वर्शन द्वारा इडेम्पोटेंट MERGE या DELETE ऑपरेशन्स करता है। डेटाबेस में कभी भी LSNs की तुलना नहीं की जाती है; ट्रांज़ैक्शन ऑर्डर एक ट्रांज़ैक्शन के भीतर LSN को सप्लीमेंट करता है।
स्नैपशॉट को प्राइमरी-की रेंज द्वारा चंक किया जाता है, प्रोग्रेस को परसिस्ट किया जाता है, और सोर्स लोड को गतिशील रूप से सीमित किया जाता है। स्नैपशॉट चलने के दौरान WAL को ड्रेन किया जाता है, और टार्गेट का सोर्स-वर्शन नियम बाउंड्री पर रिकवरी रीप्ले को अवशोषित करता है। इवेंट्स में ऑपरेशन, पहले और बाद के मान, सोर्स LSN, ट्रांज़ैक्शन आइडेंटिटी और ऑर्डर, और स्कीमा वर्शन शामिल होते हैं। सिंक केवल एक नए वर्शन को लागू करता है, इसलिए कनेक्टर रीप्ले, खोया हुआ टार्गेट एकनॉलेजमेंट, और कंज्यूमर क्रैश सभी सुरक्षित रूप से कन्वर्ज होते हैं।
डिलीट इवेंट्स क्यूरेटेड लेयर के माध्यम से बरकरार रहते हैं; टॉम्बस्टोन केवल कॉम्पैक्शन के लिए हैं। प्राइमरी-की वैल्यू परिवर्तन एक ओल्ड-की डिलीट प्लस न्यू-की क्रिएट के रूप में लागू होता है। जोड़ी गई नलेबल कॉलम संगत रूप से विकसित हो सकती हैं, जबकि ड्रॉप्स, रीनेम्स, नैरोइंग टाइप्स और की परिवर्तन नियंत्रित माइग्रेशन का उपयोग करते हैं। असंगत रिकॉर्ड चुपचाप छोड़े जाने के बजाय क्वारंटाइन किए जाते हैं और रीप्ले करने योग्य होते हैं।
ऑपरेशनल रूप से, मैं सेगमेंटेड लेटेंसी, प्रति-सोर्स LSN लैग, रिटेंड स्लॉट WAL और डिस्क हेडरूम, स्नैपशॉट प्रोग्रेस, स्कीमा क्वारंटाइन, टार्गेट विफलताएं और रिकॉन्सिलिएशन डेल्टा की निगरानी करूँगा। स्लॉट लॉस फ़ेल क्लोज़ होता है और प्रभावित दायरे के रीस्नैपशॉटिंग को ट्रिगर करता है। अंत में, मैं स्नैपशॉट के दौरान कन्करेंट राइट्स, डुप्लिकेट डिलीवरी, डिलीट, की परिवर्तन, कनेक्टर क्रैश, खोए हुए सिंक एकनॉलेजमेंट, 30 मिनट का सिंक आउटेज, स्लॉट लॉस और ब्रेकिंग स्कीमा परिवर्तन इंजेक्ट करूँगा। रो काउंट, की-बकेट चेकसम, सैंपल की गई पंक्तियाँ और कैनरी ट्रांज़ैक्शन यह साबित करेंगे कि कोई भी परिवर्तन छूटा नहीं है और कोई भी पुराना इवेंट नई स्थिति को ओवरराइट नहीं करता है।"
सामान्य गलतियाँ
- प्रत्येक टेबल को एक्सपोर्ट करना और उसके बाद ही CDC सक्षम करना → एक्सपोर्ट अंतराल से WAL गायब हो सकता है, जिससे स्नैपशॉट-टू-स्ट्रीम गैप रह जाता है → मैचिंग पॉइंट से स्ट्रीमिंग करने से पहले लॉग रिटेंशन और एक कंसिस्टेंट स्नैपशॉट पोज़ीशन स्थापित करें।
- केवल "Debezium और Kafka का उपयोग करें" कहना → प्रोडक्ट के नाम लेटेंसी, ऑर्डरिंग, रिकवरी या सिंक इडेम्पोटेंसी को परिभाषित नहीं करते हैं → पहले शुद्धता इनवेरिएंट्स और क्षमता बताएं, फिर प्रत्येक कंपोनेंट को उनसे मैप करें।
- एक ग्लोबल वर्शन के रूप में विभिन्न डेटाबेस से LSNs की तुलना करना → प्रत्येक सोर्स का एक स्वतंत्र लॉग कोऑर्डिनेट होता है → वर्शन में
source_idशामिल करें और केवल एक सोर्स सीक्वेंस के अंदर पोज़ीशन की तुलना करें। - यह मान लेना कि ब्रोकर का एग्जैक्टली-वन्स वेयरहाउस को एग्जैक्टली-वन्स बनाता है → एक बाहरी MERGE ब्रोकर ट्रांज़ैक्शन के बाहर बैठ सकता है और खोए हुए एकनॉलेजमेंट के बाद रीप्ले हो सकता है → प्राइमरी की और सोर्स वर्शन द्वारा इडेम्पोटेंट रूप से परिवर्तन लागू करें।
- एक रुके हुए कनेक्टर के लिए अनिश्चित काल तक प्रतीक्षा करना → इसका स्लॉट तब तक WAL को बनाए रख सकता है जब तक कि सोर्स स्टोरेज भर न जाए → रिटेंड बाइट्स और समाप्त होने के समय की निगरानी करें, ड्यूरेबल स्ट्रीम के साथ सिंक आउटेज को अलग करें, और स्टॉप-लॉस थ्रेशोल्ड सेट करें।
- खोए हुए स्लॉट को फिर से बनाना और सबसे नई पोज़ीशन पर जारी रखना → नए स्लॉट में कोई पुराना इतिहास नहीं होता है और यह गायब डेटा को छिपा सकता है → फ़ेल क्लोज़ करें, रीस्नैपशॉट लें, और प्रभावित दायरे को रिकॉन्सिल करें।
- टॉम्बस्टोन को एकमात्र डिलीट सिग्नल के रूप में मानना → एक कॉम्पेक्शन मार्कर रो की (key) ले जाने वाले बिज़नेस DELETE को प्रतिस्थापित नहीं कर सकता है → डिलीट इवेंट को सुरक्षित रखें और डेस्टिनेशन पर हार्ड डिलीट, सॉफ्ट डिलीट या इतिहास चुनें।
- प्रत्येक स्कीमा परिवर्तन को स्वचालित रूप से स्वीकार करना → ड्रॉप्स, नैरोइंग टाइप्स और की परिवर्तन कंज्यूमर्स या इवेंट कीज़ को तोड़ सकते हैं → एक कम्पैटिबिलिटी मैट्रिक्स को परिभाषित करें, असंगत रिकॉर्ड को क्वारंटाइन करें, और ब्रेकिंग माइग्रेशन को स्टेज करें।
- केवल 72 घंटे की स्नैपशॉट समय सीमा के लिए ऑप्टिमाइज़ करना → एक बड़ा स्कैन सोर्स p99, कैश व्यवहार और रेप्लिकेशन को नुकसान पहुंचा सकता है → 30.9 MB/s निचली सीमा का बेंचमार्क करें, गतिशील रूप से रेट-लिमिट करें, और सोर्स बजट की रक्षा करें।
- केवल कुल रो काउंट की तुलना करना → गलत तरीके से लागू किए गए अपडेट, छूटे हुए डिलीट और ऑफ़सेटिंग त्रुटियां छिपी रह सकती हैं → की बकेट द्वारा काउंट और चेकसम की तुलना करें, पंक्तियों का सैंपल लें, और कैनरी इंजेक्ट करें।
फॉलो-अप प्रश्न
फॉलो-अप 1: आप कैसे साबित करते हैं कि स्नैपशॉट के दौरान एक अपडेट और डिलीट पुराने स्नैपशॉट वैल्यू को नई स्थिति पर ओवरराइट करने की अनुमति नहीं दे सकता है?
एप्लिकेशन टाइमिंग का अनुमान लगाने के बजाय कनेक्टर के सत्यापित कंसिस्टेंट-स्नैपशॉट और लॉग-हैंडऑफ़ सिमेंटिक्स का उपयोग करें। सिंक प्रति रो एक सोर्स वर्शन स्टोर करता है और केवल नए वर्शन स्वीकार करता है, इसलिए रीप्ले किया गया READ नए UPDATE या DELETE को ओवरराइट नहीं कर सकता है। परीक्षण में, इसके स्नैपशॉट चंक के आसपास एक की को बार-बार अपडेट, डिलीट और रीक्रिएट करें, फिर अंतिम सोर्स-टू-टार्गेट समानता और सोर्स-पोज़ीशन निरंतरता का दावा (assert) करें।
फॉलो-अप 2: 30 मिनट के वेयरहाउस आउटेज के बाद आप रिकवरी समय का अनुमान कैसे लगाते हैं?
पीक बैकलॉग लगभग 108 GB है। रिकवरी समय रिकवर किए गए थ्रूपुट में से निरंतर लाइव इनग्रेस को घटाने पर निर्भर करता है। यदि लाइव ट्रैफ़िक 20 MB/s औसत पर लौटता है और कंज्यूमर्स 80 MB/s बनाए रखते हैं, तो नेट कैच-अप दर लगभग 60 MB/s है, जिससे MERGE प्रवर्धन और सुरक्षा मार्जिन से पहले सैद्धांतिक ड्रेन समय लगभग 30 मिनट हो जाता है। यदि प्रोसेसिंग केवल लाइव इनग्रेस के बराबर है, तो बैकलॉग कभी कम नहीं होता है।
फॉलो-अप 3: यदि एक सोर्स ट्रांज़ैक्शन की सभी पंक्तियों को एक साथ दिखाई देना चाहिए तो क्या बदलता है?
ट्रांज़ैक्शन-बाउंड्री मेटाडेटा को सक्षम करें, ट्रांज़ैक्शन ID द्वारा इवेंट्स को असेंबल करें, और एक पूर्ण END बाउंड्री के बाद ही ट्रांज़ैक्शन को स्टेजिंग और पब्लिकेशन के लिए कमिट करें। बड़े ट्रांज़ैक्शन को डिस्क पर बनाए रखें, टाइमआउट और रेमेडिएशन पाथ को परिभाषित करें, और ड्यूरेबल असेंबली स्थिति से फिर से शुरू करें। यह टेल लेटेंसी और स्टेट लागत को बढ़ाता है, इसलिए पहले पुष्टि करें कि संक्षिप्त क्रॉस-टेबल असंगति कंज्यूमर के लिए वास्तव में अस्वीकार्य है।
फॉलो-अप 4: यदि रेप्लिकेशन स्लॉट खो गया है लेकिन ड्यूरेबल स्ट्रीम में अभी भी सात दिनों का डेटा है, तो क्या आपको पूर्ण स्नैपशॉट चलाना होगा?
पहले संभावित गैप का पता लगाएं। यदि ड्यूरेबल स्ट्रीम में अंतिम विश्वसनीय LSN के बाद का प्रत्येक परिवर्तन शामिल है, तो रीप्ले और रिकॉन्सिलिएशन पूर्ण स्नैपशॉट के बिना निरंतरता बहाल कर सकते हैं। यदि स्लॉट इवेंट्स के स्ट्रीम तक पहुंचने से पहले गायब हो गया, या गैप बाउंड्री को साबित नहीं किया जा सकता है, तो प्रभावित टेबल या प्राइमरी-की रेंज का फिर से स्नैपशॉट लें। निर्णय डिमॉन्स्ट्रेटेबल निरंतरता का पालन करता है, दोबारा काम करने की लागत का नहीं।
फॉलो-अप 5: संपूर्ण डिज़ाइन को आउटबॉक्स से क्यों न बदलें?
एक आउटबॉक्स उत्कृष्ट होता है जब कोई सर्विस स्पष्ट रूप से डोमेन इवेंट्स जैसे ऑर्डर-क्रिएटेड या पेमेंट-कम्प्लीटेड प्रकाशित करती है और इवेंट को बिज़नेस स्टेट के समान ट्रांज़ैक्शन में लिखती है। इसके लिए एप्लिकेशन की भागीदारी की आवश्यकता होती है और इसमें केवल चयनित तथ्य होते हैं। यह समस्या एनालिटिक्स के लिए 200 टेबल में इंसर्ट, अपडेट और डिलीट को सिंक्रोनाइज़ करती है, इसलिए जेनेरिक रो-लेवल CDC आवश्यक रहता है। दोनों पैटर्न अलग-अलग कंज्यूमर्स के लिए सह-अस्तित्व में रह सकते हैं।