यहाँ एक विफलता है जिसे मैंने दो बार होते देखा, दो अलग इंजनों में। एक निर्यात 10:00 पर चलता है और जो सबसे ऊँचा अंतिम-संशोधित टाइमस्टैम्प उसने देखा उसे दर्ज करता है। 09:58 पर शुरू हुआ एक लेन-देन अभी खुला है, 10:03 पर कमिट होता है और अपने आरंभ के समय का टाइमस्टैम्प रखता है। अगला निर्यात केवल 10:00 से नई पंक्तियाँ माँगता है और उसे कभी नहीं देखता। स्थानांतरण का आकार बढ़िया था और डेटा ग़लत था।

उस निर्यात का पीछा करें जिसने एक पंक्ति खोई

SQL नहीं, घटनाओं का क्रम देखें। एप्लिकेशन पंक्ति का संशोधन-समय लेन-देन शुरू होने पर लिखता है, कमिट होने पर नहीं। निर्यातक दीवार-घड़ी का वॉटरमार्क पढ़ता है जब वह लेन-देन अभी खुला है। फिर लेन-देन सहेजे गए वॉटरमार्क से पुराने संशोधन-समय के साथ कमिट होता है। उपभोक्ता का अगला बैच वॉटरमार्क के बाद शुरू होता है, इसलिए पंक्ति कर्सर के पीछे रह जाती है और फिर कभी नहीं चुनी जाएगी।

कुछ भी त्रुटि दर्ज नहीं करता, क्योंकि कुछ भी विफल नहीं हुआ। यही इस वर्ग के बग को महँगा बनाता है: डेल्टा फ़ीड तेज़ है, पंक्ति-गणना विश्वसनीय लगती है, और खोई पंक्ति हफ़्तों बाद एक मिलान-टिकट के रूप में सामने आती है जिसे कोई दोबारा नहीं बना सकता।

क्रम-संख्याओं में दूसरे कारण से वही दोष-आकृति है। एकदिष्ट ID आपको बताती है कि मान किस क्रम में आवंटित हुए, यह नहीं कि लेन-देन किस क्रम में कमिट हुए। कम संख्या लेने वाला लेन-देन उच्च संख्या लेने वाले के बाद कमिट हो सकता है, इसलिए आवंटन-क्रम पर आधारित कर्सर भी छेद छोड़ सकता है।

फ़ीड को देने होंगे पाँच वादे

परिवहन चुनने से पहले स्रोत प्रणाली से पाँच धाराओं का अनुबंध माँगें। कोई धारा छूटे तो आपके पास अनुमान है, परिवर्तन-फ़ीड नहीं।

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

एक समर्थित तंत्र पाँचों को पूरा कर सकता है। SQL Server का परिवर्तन-ट्रैकिंग दस्तावेज़ एक ठोस प्रकाशित उदाहरण है: यह न्यूनतम मान्य संस्करण परिभाषित करता है, परिवर्तनों के साथ हटाने भी दर्ज करता है, और ऐसा स्नैपशॉट लेन-देन बताता है जो सत्यापन, संस्करण-कैप्चर और संबंधित परिवर्तन-क्वेरी को समेटता है। यह उदाहरण है कि स्रोत से क्या माँगें, वह सिंटैक्स नहीं जिसे किसी दूसरे इंजन में चिपकाया जाए।

चेकपॉइंट को पाइपलाइन का हिस्सा मानकर डिज़ाइन करें

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

cursor  = durable_checkpoint()          # last fully applied position
batch   = extract(cursor, upper_bound)  # one consistent batch
apply(batch)                            # idempotent at the target
commit()
checkpoint(batch.upper_bound)           # only now

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

हटाने के लिए अभिलेख चाहिए, निष्कर्ष नहीं

अब भी मौजूद पंक्तियों की तुलना करके उपभोक्ता को यह नहीं बताया जा सकता कि कौन-सी कुंजियाँ गायब हुईं। जो स्रोत कभी हटाना दर्ज नहीं करता, वह आपको दो अपूर्ण विकल्प देता है: तुलना के लिए पर्याप्त लंबा कुंजी-इतिहास रखना, या अनुसूची के अनुसार स्पष्ट पूर्ण मिलान चलाना। दोनों लागत वाले डिज़ाइन निर्णय हैं, और कोई भी तब तक नहीं होता जब तक कोई उसका स्वामी न हो।

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

फिर मापें कि डेल्टा सार्थक था या नहीं

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

अंतिम-संशोधित स्तंभ एक संकेत है। जो कर्सर देर के कमिट, हटाने और लंबे अवरोध को पार कर जाए वह अनुबंध है।

संबंधित लेख