इंटरव्यू प्रश्न और दायरा
एक large-scale web crawler डिज़ाइन करें जो search index को HTML प्रदान करता है। यह 10 billion ज्ञात URLs को ट्रैक करता है और प्रति दिन अधिकतम 1 billion fetches जारी कर सकता है। URL frontier, host-level politeness, deduplication, recrawling, failure recovery, और validation plan डिज़ाइन करें, जिसमें capacity estimates भी शामिल हों।
यह backend, infrastructure, search, और data-platform engineers के लिए एक senior system design प्रश्न है। आउटपुट में compressed raw HTML, fetch metadata, और नए खोजे गए links शामिल हैं। Full-text indexing, search ranking, authenticated pages, images और video, और default JavaScript rendering scope से बाहर हैं। Coverage best effort है; सिस्टम पूरे वेब को traverse करने का वादा नहीं करता है।
निम्नलिखित संख्याएँ इंटरव्यू के अनुमान हैं, प्रोडक्शन माप नहीं: एक औसत सफल response body 200 KB की है; daily fetch cap में सफलताएँ, 304 responses, विफलताओं, और retries शामिल हैं; औसत लोड पूरी daily cap का उपयोग करता है, और planned peak 25,000 fetches per second है। एक नया खोजा गया URL 60 सेकंड के भीतर durable हो जाता है। जब क्षमता उपलब्ध होती है, तो 99% overdue high-priority URLs को 10 मिनट के भीतर lease मिल जाती है। Host politeness एक hard constraint है और थ्रूपुट को पूरा करने के लिए इसमें ढील नहीं दी जा सकती।
एक सार्वजनिक इंटरव्यू रिपोर्ट 25 मिनट के डिज़ाइन राउंड का वर्णन करती है जिसमें क्रॉलर कोड पहले से मौजूद था और उम्मीदवार को एक स्केलेबल आर्किटेक्चर डिज़ाइन करना था। सार्वजनिक 2026 सिस्टम डिज़ाइन सामग्री भी distributed crawler को एक स्टैंडअलोन अभ्यास के रूप में मानती है। एक रिपोर्ट किसी कंपनी के निश्चित प्रश्न बैंक या प्रश्न की आवृत्ति को स्थापित नहीं कर सकती है, इसलिए यह लेख इसे एक प्रतिनिधि सिस्टम डिज़ाइन समस्या के रूप में मानता है और किसी कंपनी का संदर्भ नहीं देता है।
इंटरव्यूअर किन बातों का मूल्यांकन करता है
पहला सिग्नल स्कोप और अनुमान (scope and estimation) है। एक मजबूत उम्मीदवार थ्रूपुट और स्टोरेज की गणना करने से पहले क्रॉल लक्ष्य, फ्रेशनेस लक्ष्यों, डाउनस्ट्रीम कंज्यूमर और फेलियर सेमेंटिक्स को परिभाषित करता है। सीधे कतार (queue), क्रॉलर वर्कर्स और डेटाबेस बनाना यह नहीं समझाता कि उन घटकों की आवश्यकता क्यों है।
दूसरा सिग्नल URL frontier का शेड्यूलिंग इनवेरिएंट (scheduling invariant) है। एक वैश्विक FIFO काम को वितरित कर सकता है, लेकिन यह एक ही होस्ट के लिए सभी कंज्यूमर्स में कन्करेंसी, डिले और बैकऑफ़ को लागू नहीं कर सकता। एक मजबूत डिज़ाइन "कौन सा होस्ट तैयार है?" को "इस होस्ट को आगे कौन सा URL लाना चाहिए?" से अलग करता है और प्रत्येक host_key को उसकी टोकन स्थिति के लिए एक लॉजिकल ओनर देता है।
तीसरा सिग्नल तीन प्रकार के डुप्लिकेट्स के बीच अंतर करना है: समान नॉर्मलाइज़्ड URL, बाइट-समान सामग्री वाले विभिन्न URLs, और छोटे सामग्री अंतर वाले पृष्ठ। उन्हें क्रमशः सटीक URL स्थिति, एक सामग्री हैश और एक नियर-डुप्लिकेट फिंगरप्रिंट की आवश्यकता होती है। एक Bloom filter इन तीनों भूमिकाओं को पूरा नहीं कर सकता।
अंतिम सिग्नल फेलियर मॉडल (failure model) है। बाहरी फ़ेचिंग में अनिवार्य रूप से टाइमआउट, 429, 5xx, DNS त्रुटियाँ, रीडायरेक्ट लूप, विशाल प्रतिक्रियाएँ और दुर्भावनापूर्ण पृष्ठ आते हैं। एक अच्छा उत्तर at-least-once निष्पादन को स्वीकार करता है, लीज़, वर्शन-सशर्त राइट्स (version-conditional writes) और आइडम्पोटेंट पूर्णता के साथ डुप्लिकेट साइड इफ़ेक्ट्स को सीमित करता है, और ऐसे परीक्षणों और मेट्रिक्स का प्रस्ताव करता है जो डिज़ाइन को गलत साबित कर सकें।
उत्तर देने से पहले स्पष्ट करने वाले प्रश्न
- आउटपुट का उपयोग कौन करता है? एक सर्च इंडेक्स को HTML, फ़ेच समय, स्थिति और एक कैनोनिकलाइज़्ड URL की आवश्यकता होती है। एक आर्काइव को अपरिवर्तनीय वर्शनों की भी आवश्यकता होती है। एक ट्रेनिंग कॉर्पस गुणवत्ता और लाइसेंसिंग फ़िल्टर पर जोर देगा। यह समस्या केवल सर्च इंडेक्स को आउटपुट भेजती है।
- कौन-सी सामग्री दायरे में है? यह डिज़ाइन सार्वजनिक HTTP/HTTPS HTML प्राप्त करता है। PDFs, मीडिया, ऑथेंटिकेटेड सेशंस, या JavaScript रेंडरिंग फ़ेचर, पार्सर, कॉस्ट मॉडल और सुरक्षा अलगाव को बदल देंगे।
- कवरेज और ताज़गी के बीच संतुलन कैसे होना चाहिए? 10 बिलियन ज्ञात URLs में से, यह समस्या प्रतिदिन 100 मिलियन उच्च-मूल्य वाले URLs को रीफ्रेश करती है और अन्य 9.9 बिलियन के लिए 30-दिवसीय अंतराल का लक्ष्य रखती है। हर दिन हर पेज को रीफ्रेश करना 1-बिलियन-फ़ेच दैनिक बजट के साथ गणितीय रूप से असंगत है।
- politeness किस सीमा पर लागू की जाती है? डिज़ाइन
scheme + authorityसे एकhost_keyबनाता है और उस कुंजी के लिए robots नीति, कन्करेंसी, न्यूनतम विलंब और सर्वर-निर्देशित बैकऑफ़ को केंद्रीकृत करता है। एक बातचीत किया गया अलाउंस केवल उस होस्ट की नीति को बदलता है, वैश्विक इनवेरिएंट को नहीं। - “कोई डुप्लिकेट नहीं” की शर्त कितनी सख्त है? Bloom-filter फ़ाल्स पॉज़िटिव के कारण URL डिस्कवरी को चुपचाप URL नहीं खोना चाहिए, इसलिए एक टिकाऊ विशिष्ट कुंजी (durable unique key) ही सच्चाई का स्रोत (source of truth) है। नेटवर्क फ़ेच दोहराए जा सकते हैं; स्टोरेज और डाउनस्ट्रीम इवेंट्स आइडम्पोटेंट होने चाहिए।
- हटाए गए और विफल पेज कितने समय तक रखे जाते हैं? एक
404, एक410, बार-बार की विफलताएं, और एक अस्थायी5xxके लिए अलग-अलग पुनरीक्षण अंतरालों की आवश्यकता होती है। यह डिज़ाइन एक टॉम्बस्टोन और नवीनतम स्थिति को बनाए रखता है ताकि पुनर्खोज एक नया URL न बनाए।
30 सेकंड का उत्तर
“प्रति दिन एक बिलियन फ़ेच औसतन लगभग 11,600 प्रति सेकंड है, इसलिए मैं 25,000-प्रति-सेकंड पीक की योजना बनाऊँगा और फ्रेशनेस को दैनिक रूप से रीफ्रेश किए जाने वाले 100 मिलियन URLs और हर 30 दिनों में रीफ्रेश किए जाने वाले 9.9 बिलियन URLs में विभाजित करूँगा। डिस्कवरी रूढ़िवादी नॉर्मलाइज़ेशन और सटीक यूनिक-की डिडुप्लिकेशन करती है। फ्रंटियर को होस्ट द्वारा शार्ड किया जाता है: एक शार्ड पहले उस होस्ट को चुनता है जिसका next_allowed_at आ गया है, फिर उस होस्ट की कतार से उच्चतम-प्राथमिकता वाला URL लेता है। यह robots नीति, कन्करेंसी और बैकऑफ़ को एक ओनर देता है। फ़ेचर्स लीज़ और कंडीशनल रिक्वेस्ट्स का उपयोग करते हैं, ऑब्जेक्ट स्टोरेज में HTML लिखते हैं, और इसे पार्सर को भेजते हैं जो डिस्कवरी के माध्यम से लिंक वापस फ़ीड करते हैं। निष्पादन at-least-once है; URL वर्शन्स और आइडम्पोटेंट पूर्णता डुप्लिकेट्स को एब्जॉर्ब करते हैं। मैं प्रति-होस्ट दर सीमा, लीज़ समाप्ति, 429/503, अप्राप्य robots फ़ाइलें, रीडायरेक्ट लूप और क्रॉलर ट्रैप्स पर सत्यापन केंद्रित करूँगा।”
चरण-दर-चरण गहन विश्लेषण
चरण 1: साबित करें कि लक्ष्य बजट में पूरे हो सकते हैं
86,400 सेकंड से विभाजित एक बिलियन फ़ेच औसतन लगभग 11,574 फ़ेच प्रति सेकंड है। ट्रैफ़िक भिन्नता और कैच-अप कार्य को ध्यान में रखते हुए, नियोजित पीक को 25,000 प्रति सेकंड तक राउंड करें। यदि प्रत्येक प्रतिक्रिया 200 KB की बॉडी लौटाती है, तो इनग्रेस प्रति दिन अधिकतम लगभग 200 TB, या औसतन 2.31 GB प्रति सेकंड होगा। एक 304 Not Modified में कोई प्रतिक्रिया सामग्री नहीं होती है, इसलिए वास्तविक इनग्रेस इस रूढ़िवादी सीमा से कम होना चाहिए और इसे लोड परीक्षणों और देखे गए वितरणों के साथ कैलिब्रेट किया जाना चाहिए।
दैनिक पुनरीक्षण योजना के लिए आवश्यक है:
100,000,000 + 9,900,000,000 / 30 = 430,000,000 fetches
यह नए खोजे गए पृष्ठों, पुनरावृत्तियों और तेजी से बदलने वाले पृष्ठों के लिए लगभग 570 मिलियन फ़ेच छोड़ता है। प्रति URL 200 बाइट्स की कच्ची लॉजिकल स्थिति मानकर, 10 बिलियन URL रिकॉर्ड्स के लिए लगभग 2 TB की आवश्यकता होती है। रेप्लिकेशन, इंडेक्स, LSM एम्प्लीफिकेशन और ऑब्जेक्ट स्टोरेज को बाहर रखा गया है। यह ऑर्डर ऑफ मैग्नीट्यूड क्षैतिज रूप से विभाजित मेटाडेटा और HTML के लिए अलग ऑब्जेक्ट स्टोरेज की मांग करता है; पेज बॉडीज फ्रंटियर से संबंधित नहीं हैं।
चरण 2: चरणबद्ध डेटा प्रवाह बनाएँ
पूरा पथ है: seeds और Sitemaps → URL discovery और normalization → exact seen state → URL metadata → frontier scheduler → robots और host-politeness check → DNS/HTTP fetcher → HTML object storage → parser → discovered links वापस discovery में। पार्स किया गया आउटपुट और fetch-completion इवेंट्स फिर सर्च इंडेक्स और रीविजिट कैलकुलेटर में जाते हैं।
एक Sitemap बीजों (seeds) का पूरक है; यह कवरेज की गारंटी नहीं देता है। एक Sitemap फ़ाइल में अधिकतम 50,000 URLs हो सकते हैं और यह अनकंप्रेस्ड अधिकतम 50 MB हो सकती है। बड़ी साइटें उन्हें एक Sitemap इंडेक्स के पीछे विभाजित करती हैं। लिंक डिस्कवरी, Sitemaps, और ऑपरेटर द्वारा प्रदान किए गए बीज सभी एक ही डिडुप्लिकेशन एंट्री पॉइंट का उपयोग करते हैं ताकि तीन स्टेट मशीनें असहमत न हो सकें।
फ़ेच को पार्स से अलग करने के दो सीधे फायदे हैं। धीमा बाहरी I/O पार्सर CPU पर कब्जा नहीं करता है, और एक पार्सर क्रैश साइट से दोबारा संपर्क किए बिना संग्रहीत HTML को फिर से चला (replay) सकता है। प्रत्येक चरण को एक बाउंडेड कतार और बैकप्रेशर की आवश्यकता होती है ताकि पार्सिंग या स्टोरेज क्षमता से अधिक अस्थायी डाउनलोड दर मेमोरी को समाप्त न कर सके।
चरण 3: होस्ट शिष्टाचार को frontier की शेड्यूलिंग इकाई बनाएँ
फ्रंटियर दो कतार स्तरों का उपयोग करता है। ऊपरी स्तर प्रत्येक होस्ट के next_allowed_at और प्राथमिकता को संग्रहीत करता है और केवल उन होस्ट्स का चयन करता है जो तैयार हैं और बैकऑफ़ में नहीं हैं। निचला स्तर उस होस्ट के लिए URLs की एक प्राथमिकता कतार है, जिसे व्यावसायिक मूल्य, देय समय, लिंक गहराई और ऐतिहासिक परिवर्तन दर जैसे संकेतों द्वारा ऑर्डर किया गया है। एक URL को लीज पर देने से होस्ट की in_flight संख्या और अगला योग्य समय स्वचालित रूप से (atomically) अपडेट हो जाता है।
host_key को हैश करना एक होस्ट को एक शेड्यूलर शार्ड असाइन करता है। भले ही किसी होस्ट के पास दस लाख पेंडिंग URLs हों, एक लॉजिकल ओनर उसके टोकन देता है जबकि फ़ेच का काम कई मशीनों पर चल सकता है। एक हॉट होस्ट के पास कई कन्करेंट कनेक्शन हो सकते हैं, लेकिन वही होस्ट स्थिति अभी भी इसके अलाउंस को नियंत्रित करती है। वर्कर्स जोड़ने से विभिन्न होस्ट्स में समानता (parallelism) बढ़ती है; यह कानूनी रूप से किसी एक होस्ट के अलाउंस को पार नहीं कर सकता।
robots.txt सेवा के शीर्ष-स्तरीय /robots.txt से प्राप्त किया जाता है। एक सफल फ़ेच के लिए क्रॉलर को पार्स करने योग्य नियमों का पालन करना आवश्यक है। जब फ़ाइल 400–499 के साथ अनुपलब्ध होती है, तो प्रोटोकॉल एक्सेस की अनुमति देता है; जब नेटवर्क त्रुटियां या 500–599 इसे अप्राप्य बना देते हैं, तो क्रॉलर पूर्ण अस्वीकृति (complete disallow) मानता है। एक कैश्ड कॉपी का उपयोग आम तौर पर 24 घंटे से अधिक नहीं किया जाना चाहिए जब तक कि फ़ाइल अप्राप्य न हो। “एक कन्करेंट अनुरोध और प्रति होस्ट एक सेकंड की देरी” केवल इस साक्षात्कार का कॉन्फ़िगर करने योग्य डिफ़ॉल्ट है; प्रोटोकॉल कोई सार्वभौमिक दर परिभाषित नहीं करता है। 429 या 503 पर, Retry-After का सम्मान करें; जब यह अनुपस्थित हो, तो जिटरेड एक्सपोनेंशियल बैकऑफ़ लागू करें और उस होस्ट के अलाउंस को कम करें।
चरण 4: URL डीडुप्लिकेशन को कंटेंट डीडुप्लिकेशन से अलग रखें
नॉर्मलाइज़ेशन केवल सेमेंटिक्स-प्रिजर्विंग रूपांतरण करता है: रिलेटिव संदर्भों को हल करना, फ्रैगमेंट को हटाना, स्कीम और होस्टनाम केस को नॉर्मलाइज़ करना, डिफ़ॉल्ट पोर्ट्स को संभालना, और पाथ डॉट-सेगमेंट को हल करना। क्वेरी पैरामीटर्स को विश्व स्तर पर न हटाएं या पुनर्व्यवस्थित न करें; कुछ साइटें क्रम और दोहराई गई कुंजियों को अर्थ देती हैं। एक पेज-घोषित कैनोनिकल URL स्कोरिंग और क्लस्टरिंग को प्रभावित कर सकता है, लेकिन इसे देखे गए URL को तथ्य के रूप में अधिलेखित नहीं करना चाहिए।
विभाजित मेटाडेटा स्टोर में canonical_url, या इसके लिए एक टकराव-सुरक्षित (collision-safe) विशिष्ट कुंजी संग्रहीत करें। एक Bloom filter केवल एक नकारात्मक त्वरक (negative accelerator) है: "निश्चित रूप से अनुपस्थित" पर, सीधे डालने का प्रयास करें; "संभवतः मौजूद" पर, फिर भी टिकाऊ अद्वितीय कुंजी की जांच करें। इसलिए एक गलत सकारात्मक (false positive) एक पृष्ठ को छोड़ने के बजाय एक रीड जोड़ता है। पूर्ण URL या दूसरे फ़िंगरप्रिंट की तुलना करके हैश टकराव को हल करें।
फ़ेच करने के बाद ही सामग्री हैश की गणना करें। बाइट-समान सामग्री प्रत्येक URL के मेटाडेटा को संरक्षित करते हुए एक ऑब्जेक्ट का पुनर्चक्रण कर सकती है। लगभग डुप्लिकेट पृष्ठों को SimHash जैसे फ़िंगरप्रिंट के साथ समूहीकृत किया जा सकता है। शोध ने मल्टी-बिलियन-पेज पैमाने पर इस वर्ग के फ़िंगरप्रिंट का प्रदर्शन किया है, लेकिन नियर-डुप्लिकेट सिग्नल स्टोरेज, इंडेक्सिंग या रीविजिट प्राथमिकता के इनपुट के रूप में अधिक सुरक्षित है। किसी पेज को सीधे छोड़ देने से वे लिंक भी छूट सकते हैं जो केवल उसी पेज के लिए विशिष्ट हैं।
चरण 5: संस्करणित स्थिति और लीज़ से पुनर्प्राप्ति करें
कोर रिकॉर्ड्स को कॉम्पैक्ट रखें:
UrlState( urlid, canonicalurl, hostkey, stateversion, lastfetchat, nextfetchat, priority, etag, lastmodified, contenthash, failure_count )
HostState( hostkey, robotspolicy, robotsexpiresat, nextallowedat, inflight, backoffuntil, policy_version )
FetchLease(leaseid, urlid, urlversion, expiresat, attempt)
शेड्यूलर url_version युक्त एक सीमित लीज़ जारी करता है। एक फ़ेचर HTML लिखने के बाद लेकिन कार्य को स्वीकार (acknowledge) करने से पहले क्रैश हो सकता है, इसलिए लीज़ की समाप्ति एक और फ़ेच का कारण बन सकती है। समाप्ति (url_id, url_version) पर एक सशर्त राइट (conditional write) का उपयोग करती है। एक पुरानी लीज़ या डुप्लिकेट पावती मौजूदा परिणाम लौटाती है और दूसरा इंडेक्स इवेंट प्रकाशित नहीं करती है। एक नया रीविजिट पहले वर्शन को बढ़ाता है, इसलिए पिछले दौर की आइडम्पोटेंसी कुंजी वैध नए कार्य को दबा नहीं सकती है।
जब एक ETag उपलब्ध हो, तो If-None-Match भेजें; अन्यथा एक संग्रहीत Last-Modified, If-Modified-Since को चला सकता है। एक 304 खाली बॉडी लिखे बिना फ़ेच समय और अगले शेड्यूल को अपडेट करता है। DNS टाइमआउट, कनेक्शन विफलता और 5xx एक कैप्ड रीट्राई नीति में प्रवेश करते हैं। एक स्थायी 404/410 एक टॉम्बस्टोन और एक बहुत लंबा रीविजिट अंतराल बनाता है। रीडायरेक्ट्स में हॉप सीमा और लूप डिटेक्शन होता है।
चरण 6: दोबारा विज़िट, ट्रैप सुरक्षा और सिक्योरिटी को एक ही बजट में रखें
रीविजिट प्राथमिकता पेज मूल्य, हालिया परिवर्तन अंतराल, स्थिति और साइट अलाउंस को जोड़ती है। सामग्री में बदलाव अंतराल को छोटा करता है; बार-बार अपरिवर्तित परिणाम इसे लंबा करते हैं, जो एक और 30 दिनों के बीच क्लैम्प्ड होता है। यह न्यूनतम ताजगी की गारंटी बनाए रखते हुए स्थिर पृष्ठों से बदलते पृष्ठों में बजट स्थानांतरित करता है।
अकेले अधिकतम लिंक गहराई कैलेंडर, पहलू नेविगेशन (faceted navigation), या अनबाउंडेड क्वेरी संयोजनों को नहीं रोकती है। प्रति-होस्ट दैनिक बजट, URL-टेम्पलेट वृद्धि सीमाएं, क्वेरी-पैरामीटर गणना, दोहराए गए पाथ डिटेक्शन, प्रतिक्रिया-बॉडी और डीकंप्रेस्ड-आकार सीमाएं, पार्सर-समय सीमाएं और रीडायरेक्ट-हॉप सीमाएं जोड़ें। जब कोई पैटर्न अपना बजट समाप्त कर लेता है, तो उस पैटर्न को रोकें और असंबंधित होस्ट्स को ब्लॉक किए बिना एक नमूना रखें।
फ़ेचर्स अविश्वसनीय इनपुट को प्रोसेस करते हैं। SSRF और DNS-rebinding जोखिम को कम करने के लिए DNS परिणामों से लूपबैक, निजी, लिंक-लोकल और क्लाउड-मेटाडेटा पतों को अस्वीकार करें और कनेक्ट करने से ठीक पहले उन्हें फिर से जांचें। पार्सर्स को मेमोरी और सीपीयू सीमाओं के साथ चलाएं और कम्प्रेशन बम और मैलफॉर्मड HTML को अलग करें। Robots नियम क्रॉल प्राथमिकताओं को व्यक्त करते हैं; वे एक्सेस ऑथराइजेशन नहीं हैं।
चरण 7: फॉल्ट इंजेक्शन से इनवेरिएंट्स सत्यापित करें
एक नियतात्मक (deterministic) शेड्यूलिंग सिमुलेशन से शुरुआत करें। तीन होस्ट्स को अलग-अलग दरें, robots नियम और Retry-After मान दें; वर्चुअल क्लॉक को आगे बढ़ाएं; दावा करें कि कोई भी समय विंडो किसी अलाउंस से अधिक नहीं है और एक अस्वीकृत पाथ को कभी भी लीज़ प्राप्त नहीं होती है। फिर "HTTP सफलता के बाद प्रक्रिया क्रैश", "लीज़ पावती खो गई है", "robots कैश समाप्त हो गया है", "DNS एक निजी पते पर हल होता है", और "पार्सर कतार रुक जाती है" इंजेक्ट करें। कार्यों को पुनर्प्राप्त होना चाहिए, इंडेक्स इवेंट्स अद्वितीय रहने चाहिए, और फ़ेच चरण को बैकप्रेशर लागू करना चाहिए।
क्षमता परीक्षणों में प्रति सेकंड 25,000 लीज़ अनुदान, 10-बिलियन-URL कीस्पेस में विभाजन तिरछापन (partition skew), और दस लाख लंबित URLs वाला एक हॉट होस्ट शामिल होना चाहिए। मुख्य मेट्रिक्स में पात्र लैग, फ़ेच और बाइट दरें, 2xx/304/429/5xx अनुपात, होस्ट-नीति उल्लंघन, लीज़ पुनरावृत्ति, URL और सामग्री डुप्लिकेट दरें, robots-कैश आयु, पार्सर बैकलॉग और बजट-ट्रिगर दर शामिल हैं। होस्ट-नीति उल्लंघन शून्य रहना चाहिए; politeness का उल्लंघन करते हुए औसत थ्रूपुट को पूरा करना एक असफल परीक्षण है।
विकल्प और उनकी सीमाएँ
स्वामित्व वाली साइटों के खिलाफ प्रति दिन कुछ मिलियन फ़ेच पर, एक रिलेशनल डेटाबेस next_fetch_at को इंडेक्स कर सकता है, कार्यों का दावा करने के लिए SKIP LOCKED का उपयोग कर सकता है, और उसी लेनदेन में एक होस्ट टोकन को अपडेट कर सकता है। इसे तैनात करना और डीबग करना आसान है। प्रति दिन एक बिलियन फ़ेच पर, वैश्विक इंडेक्स स्कैन, हॉट अपडेट और क्लीनअप बाधा बन जाते हैं, जिससे दो-स्तरीय विभाजित फ्रंटियर एक बेहतर फिट बन जाता है।
देखे गए सेट के रूप में Bloom filter का उपयोग करने से रीड्स की बचत होती है, लेकिन फ़ाल्स पॉज़िटिव स्थायी रूप से कवरेज को कम करते हैं। यह डिज़ाइन इसे एक कैश के रूप में डिमोट करता है और टिकाऊ अद्वितीय कुंजी को सच्चाई के स्रोत के रूप में रखता है। पुष्टिकरण रीड को छोड़ना केवल तभी उचित है जब उत्पाद स्पष्ट रूप से एक निर्धारित फ़ाल्स-पॉज़िटिव बजट को स्वीकार करता है।
मज़बूत उत्तर का उदाहरण
“मैं दो इनवेरिएंट्स के साथ शुरुआत करूँगा: बजट और पोलाइटनेस। प्रति दिन एक बिलियन फ़ेच औसतन लगभग 11,600 प्रति सेकंड और 25,000 प्रति सेकंड पीक है। प्रतिदिन 100 मिलियन URLs और प्रत्येक 30 दिनों में 9.9 बिलियन URLs को रीफ्रेश करने से प्रति दिन लगभग 430 मिलियन फ़ेच शेड्यूल होते हैं, जिससे डिस्कवरी, रिट्राई और चेंज-संचालित रीफ्रेश के लिए जगह बचती है। प्रति प्रतिक्रिया 200 KB पर, 200 TB प्रति दिन एक रूढ़िवादी नेटवर्क ऊपरी सीमा है; 304 प्रतिक्रियाएँ वास्तविक ट्रैफ़िक को कम करती हैं।
प्रवेश पर, एक URL केवल सुरक्षित नॉर्मलाइज़ेशन प्राप्त करता है और एक टिकाऊ अद्वितीय कुंजी के विरुद्ध जाँचा जाता है। एक Bloom filter केवल स्पष्ट रूप से अनदेखे URLs के लिए रीड्स से बचता है। फ्रंटियर को scheme + authority द्वारा विभाजित किया गया है; प्रत्येक शार्ड होस्ट की तैयारी और प्रति-होस्ट URL प्राथमिकता कतार बनाए रखता है। काम का दावा करना स्वचालित रूप से एक होस्ट टोकन का उपभोग करता है, इसलिए कई फ़ेचर्स सामूहिक रूप से एक साइट को ओवरलोड नहीं कर सकते हैं। एक अप्राप्य robots फ़ाइल होस्ट को रोक देती है, और 429/503, Retry-After या जिटरेड बैकऑफ़ को ट्रिगर करता है।
एक फ़ेचर एक बाउंडेड लीज़ प्राप्त करता है, एक कंडीशनल GET करता है, ऑब्जेक्ट स्टोरेज में HTML लिखता है, और पार्सिंग को अगले चरण में सौंपता है। पार्स किए गए लिंक उसी डिस्कवरी एंट्री पॉइंट के माध्यम से वापस आते हैं। लीज़ की समाप्ति एक अनुरोध को दोहरा सकती है, लेकिन URL-वर्शन्ड पूर्णता एक पुरानी लीज़ को स्थिति को अधिलेखित करने या दूसरा इंडेक्स इवेंट उत्सर्जित करने से रोकती है। एक सामग्री हैश सटीक डुप्लिकेट ऑब्जेक्ट्स का पुनर्चक्रण करता है, जबकि SimHash संभावित रूप से अद्वितीय लिंक को त्यागने के बजाय नियर-डुप्लिकेट प्राथमिकता को प्रभावित करता है।
मैं एक वर्चुअल क्लॉक के साथ प्रति-होस्ट अंतराल को साबित करूँगा और राइट के बाद क्रैश, खोई हुई पावती, समाप्त robots स्थिति, DNS रीबाइंडिंग, और पार्सर बैकप्रेशर को इंजेक्ट करूँगा। स्वीकृति के लिए 25,000-प्रति-सेकंड पीक और शून्य होस्ट-नीति उल्लंघन दोनों की आवश्यकता होती है।”
सामान्य गलतियाँ
- गलती: एक वैश्विक संदेश कतार का उपयोग करना। यह क्यों विफल होता है: स्वतंत्र कंज्यूमर्स संयुक्त रूप से किसी होस्ट के अगले योग्य समय को लागू नहीं कर सकते हैं, इसलिए उच्च थ्रूपुट politeness के उल्लंघन के जोखिम को बढ़ाता है। समाधान:
host_keyद्वारा शेड्यूलिंग स्वामित्व असाइन करें और एक होस्ट-रेडी कतार प्लस प्रति-होस्ट URL कतारों का उपयोग करें। - गलती: Bloom filter को ही एकमात्र seen set बनाना। यह क्यों विफल होता है: एक गलत सकारात्मक (false positive) स्थायी रूप से एक अनदेखे URL को छोड़ देता है, और फ़िल्टर स्थिति, वर्शन या रीविजिट समय को संग्रहीत नहीं कर सकता है। समाधान: इसे केवल एक कैश के रूप में उपयोग करें और टिकाऊ अद्वितीय-कुंजी स्थिति रखें।
- गलती: URL deduplication को content deduplication समझना। यह क्यों विफल होता है: विभिन्न URLs समान सामग्री लौटा सकते हैं, और एक URL समय के साथ बदल सकता है। समाधान: डिस्कवरी के दौरान सटीक URLs को डिडुप्लिकेट करें, फिर फ़ेच करने के बाद एक सामग्री हैश और नियर-डुप्लिकेट फ़िंगरप्रिंट की गणना करें।
- गलती: exactly-once crawling का वादा करना। यह क्यों विफल होता है: बाहरी HTTP सफलता और आंतरिक पावती एक एकल परमाणु लेनदेन (atomic transaction) नहीं बना सकते हैं, जिससे क्रैश विंडो रह जाती है। समाधान: at-least-once निष्पादन को स्वीकार करें और लीज़, वर्शन-सशर्त राइट्स और आइडम्पोटेंट इवेंट्स के साथ आंतरिक दुष्प्रभावों को नियंत्रित करें।
- गलती: robots की हर त्रुटि पर crawling जारी रखना। यह क्यों विफल होता है: प्रोटोकॉल अनुपलब्ध (unavailable) और अप्राप्य (unreachable) के बीच अंतर करता है; एक नेटवर्क त्रुटि या
5xxके लिए पूर्ण अस्वीकृति की आवश्यकता होती है। समाधान: एक स्पष्ट स्टेट मशीन लागू करें और कैश आयु, रीडायरेक्ट्स और विफलता वर्गों का अलग से परीक्षण करें। - गलती: crawler traps के लिए केवल अधिकतम depth पर निर्भर रहना। यह क्यों विफल होता है: एक ही गहराई में अनबाउंडेड पहलू, कैलेंडर और क्वेरी-पैरामीटर संयोजन हो सकते हैं। समाधान: होस्ट बजट, URL-पैटर्न वृद्धि, पैरामीटर गणना, प्रतिक्रिया-आकार और पार्सर-समय सीमाओं को मिलाएं।
आगे के प्रश्न
अगर 50% लंबित URL एक ही होस्ट के हों तो क्या होगा?
पहले वह कन्करेंसी और दर स्थापित करें जिसकी साइट अनुमति देती है। एक निश्चित अलाउंस के साथ, अधिक वर्कर्स उस होस्ट के वैध थ्रूपुट को नहीं बढ़ा सकते हैं; वे केवल अन्य होस्ट्स में समानता में सुधार करते हैं। स्टोरेज हॉटस्पॉट को कम करने के लिए होस्ट की URL कतार को विभाजित किया जा सकता है, लेकिन प्रत्येक विभाजन अभी भी एक लॉजिकल टोकन सेवा से क्षमता का अनुरोध करता है। यदि व्यवसाय को अधिक गति की आवश्यकता है, तो साइट के साथ एक समर्पित फ़ीड या बड़े अलाउंस पर बातचीत करें और नई नीति का वर्शन बनाएं।
exactly-once की गारंटी क्यों न दें?
फ़ेचर HTTP प्रतिक्रिया प्राप्त करने के बाद और अपनी लीज़ को स्वीकार करने से पहले क्रैश हो सकता है, और बाहरी साइट आंतरिक लेनदेन में भाग नहीं लेती है। एक वितरित लेनदेन उस GET को पूर्ववत नहीं कर सकता जो पहले ही हो चुका है। प्राप्त करने योग्य अनुबंध at-least-once दावा, संभावित डुप्लिकेट फ़ेच, और आइडम्पोटेंट आंतरिक पूर्णता है। डुप्लिकेट दर को मापें और सशर्त अनुरोधों के साथ इसकी लागत को कम करें।
अगर पेज की सामग्री दिखाने के लिए JavaScript आवश्यक हो तो क्या होगा?
सामान्य HTTP फ़ेचिंग को पहले स्तर के रूप में रखें। केवल तभी जब पार्सिंग खाली हो, साइट नीति इसकी अनुमति देती हो, और पेज मूल्य एक सीमा को पार करता हो, एक URL को एक अलग रेंडरिंग कतार में प्रवेश करना चाहिए। रेंडरर्स के पास कम कन्करेंसी और सख्त CPU, मेमोरी और समय बजट होते हैं, और वे मूल होस्ट टोकन साझा करते हैं। अन्यथा महंगा रेंडरिंग politeness को बायपास कर देगा और वैश्विक बजट का उपभोग करेगा।
एक ही होस्ट को दो बार हिट किए बिना crawler को कई क्षेत्रों में कैसे चलाएँ?
प्रत्येक host_key को एक होम रीजन असाइन करें और केवल उसी रीजन को होस्ट टोकन देने की अनुमति दें; अन्य रीजन पार्स और स्टोर कर सकते हैं। एक क्षेत्रीय विफलता पर, एक फ़ेंसिंग टोकन ले जाने वाली लीज़ के साथ स्वामित्व स्थानांतरित करें। काम देने से पहले बरामद पुराने क्षेत्र के पास नया epoch होना चाहिए। कई क्षेत्रों में एक ही होस्ट के लिए सक्रिय शेड्यूलिंग politeness इनवेरिएंट का उल्लंघन करेगी।
स्टोरेज लागत अचानक बजट से अधिक हो जाए तो सबसे पहले क्या घटाएँ?
पहले कंडीशनल-रिक्वेस्ट हिट्स, कम्प्रेशन और सटीक डुप्लिकेट ऑब्जेक्ट्स के पुनर्चक्रण में सुधार करें। फिर सामग्री मूल्य के अनुसार raw-HTML प्रतिधारण को छोटा करें। इसके साथ URL मेटाडेटा और फ़ेच ऑडिट रिकॉर्ड्स को न हटाएं; रीविज़िट, डिडुप्लिकेशन और अनुपालन जांच उस स्थिति पर निर्भर करते हैं। नियर-डुप्लिकेट डिटेक्शन प्राथमिकता को कम कर सकता है या एक स्टोरेज टियर चुन सकता है, लेकिन इसे अप्रमाणित बल्क डिलीशन को ट्रिगर नहीं करना चाहिए।