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

System Design Interview: URL Shortener डिज़ाइन करें

सिस्टम डिज़ाइनमध्यम
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक URL shortening सर्विस डिज़ाइन करें जो यूनीक शॉर्ट लिंक बनाती है और उन्हें उच्च उपलब्धता (high availability) और लो लेटेंसी के साथ रीडायरेक्ट करती है। APIs, डेटा मॉडल, कोड जनरेशन, स्केलिंग, कंसिस्टेंसी, विफलता प्रबंधन (failure handling), और सुरक्षा ट्रेड-ऑफ़ की व्याख्या करें।

प्रॉम्प्ट और स्कोप

एक ऐसी सर्विस डिज़ाइन करें जो HTTP या HTTPS URL स्वीकार करती है और एक छोटा लिंक लौटाती है। शॉर्ट लिंक पर जाने से उपयोगकर्ता संग्रहीत गंतव्य (destination) पर रीडायरेक्ट होना चाहिए। बेस डिज़ाइन एक वैकल्पिक कस्टम उपनाम (custom alias) और समाप्ति समय (expiration time) का समर्थन करता है। क्लिक एनालिटिक्स, कस्टम डोमेन, खाता प्रबंधन (account management), और लिंक पूर्वावलोकन (link previews) मुख्य आवश्यकताओं के बजाय फॉलो-अप हैं।

इन केस मान्यताओं का उपयोग करें ताकि प्रत्येक क्षमता का दावा पुनरुत्पादित किया जा सके:

  • प्रति दिन 1 मिलियन नए लिंक और 100 मिलियन रीडायरेक्ट;
  • ट्रैफ़िक दैनिक औसत के 10 गुना तक पहुँच जाता है;
  • लिंक पाँच वर्षों तक बनाए रखे जाते हैं जब तक कि वे समाप्त या अक्षम न हो जाएँ;
  • रीडायरेक्ट पाथ का लक्ष्य 99.99% मासिक उपलब्धता और p99 सर्विस लेटेंसी 100 ms से कम रखना है;
  • इंडेक्स और प्रतिकृति (replication) से पहले एक संग्रहीत मैपिंग का औसत 500 बाइट्स होता है।

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

इंटरव्यूअर क्या मूल्यांकन करता है

पहला संकेत आवश्यकता नियंत्रण (requirement control) है। एक उपयोगी उत्तर एनालिटिक्स और खाता सुविधाओं से लिंक निर्माण और रीडायरेक्शन को अलग करता है, यह परिभाषित करता है कि क्या गंतव्य बदल सकते हैं, और पूछता है कि समाप्ति और कस्टम उपनाम कैसे व्यवहार करते हैं। उन अनुबंधों (contracts) को परिभाषित करने से पहले कतार (queue), सर्च इंजन या ग्राफ़ डेटाबेस जोड़ना डिज़ाइन को कमजोर करता है।

दूसरा संकेत यह है कि क्या स्केल अनुमान निर्णयों को बदलते हैं। माना गया कार्यभार प्रति सेकंड औसतन लगभग 12 निर्माण और 1,200 रीडायरेक्ट का है, जिसमें पीक क्रमशः 120 और 12,000 प्रति सेकंड के करीब है। पाँच वर्षों के निर्माण से लगभग 1.8 बिलियन मैपिंग और लगभग 0.9 TB कच्चा मैपिंग डेटा प्राप्त होता है। रेप्लिकेशन, इंडेक्स, स्टोरेज ओवरहेड और हेडरूम प्रोविज़न किए गए फ़ुटप्रिंट को कई गुना बड़ा बना देते हैं। ये संख्याएँ एक पार्टिशनेबल ड्यूरेबल स्टोर और कैश को सही ठहराती हैं, लेकिन वे हर संभव वितरित घटक (distributed component) को उचित नहीं ठहराती हैं।

तीसरा संकेत पहचानकर्ता की शुद्धता (identifier correctness) है। एक आठ-वर्ण वाले Base62 कोड में 62^8, या लगभग 218 ट्रिलियन, संभावित मान होते हैं। 1.8 बिलियन बनाए रखे गए लिंक पर, अधिभोग (occupancy) 0.001% से कम है। इसलिए एक नए रैंडम चयन में कोलिजन की संभावना बहुत कम होती है, फिर भी पर्याप्त चयनों के बाद सिस्टम द्वारा किसी कोलिजन को देखे जाने की संभावना बड़ी हो जाती है। रैंडमनेस पूर्वानुमेयता (predictability) को कम करती है; यह विशिष्टता की गारंटी नहीं देती है। ड्यूरेबल राइट को परमाणु रूप से (atomically) यह पुष्टि करनी चाहिए कि कोड मौजूद नहीं है और रैंडम कोलिजन को पुनः प्रयास (retry) करना चाहिए।

चौथा संकेत रीड-पाथ और विफलता तर्क (failure reasoning) है। कैश एक अनुकूलन (optimization) है, सत्य का स्रोत (source of truth) नहीं। क्लीनअप कार्य पर निर्भर रहने के बजाय रीड्स के दौरान समाप्ति की जाँच की जानी चाहिए। एक हॉट की (hot key), कैश आउटेज, डेटाबेस टाइमआउट, डुप्लीकेट POST, क्षेत्रीय रेप्लिकेशन लैग, एनालिटिक्स बैकलॉग, और आपातकालीन टेकडाउन प्रत्येक के लिए एक स्पष्ट व्यवहार की आवश्यकता होती है।

अंत में, एक मजबूत उत्तर सुरक्षा को एक मुख्य रीडायरेक्ट आवश्यकता मानता है। शॉर्ट लिंक फ़िशिंग गंतव्यों को छिपा सकते हैं और पूर्वानुमेय कोड गणना (enumeration) को सक्षम कर सकते हैं। URL पार्सिंग, स्वीकृत स्कीमा, दर सीमाएं (rate limits), प्रतिष्ठा जांच (reputation checks), दुरुपयोग रिपोर्टिंग, त्वरित अक्षमता, और गैर-अनुक्रमिक सार्वजनिक कोड डिज़ाइन में होने चाहिए, न कि एक सामान्य "सुरक्षा बाद में जोड़ें" बॉक्स में।

उत्तर देने से पहले स्पष्ट करने वाले प्रश्न

  • क्या निर्माण के बाद गंतव्य बदल सकता है? बेस मैपिंग अपरिवर्तनीय (immutable) है। अपरिवर्तनीयता कैशिंग और ऑडिट इतिहास को सरल बनाती है। यदि संपादन की आवश्यकता है, तो वर्ज़निंग और एक सख्त अमान्यीकरण (invalidation) SLO जोड़ें।
  • क्या समान लंबे URLs को एक ही कोड साझा करना चाहिए? नहीं। विभिन्न स्वामियों, अभियानों, समाप्ति समयों और नीतियों को अलग-अलग लिंक की आवश्यकता हो सकती है। डिडुप्लीकेशन एक स्पष्ट विकल्प हो सकता है, गंतव्य को हैश करने का आकस्मिक दुष्प्रभाव नहीं।
  • क्या कस्टम उपनाम आवश्यक हैं? वे वैकल्पिक हैं और चयनित डोमेन में अद्वितीय हैं। एक विरोध (conflict) 409 लौटाता है; सेवा कभी भी अनुरोधित उपनाम को चुपचाप नहीं बदलती है।
  • समाप्ति पर क्या होता है? एक ज्ञात समाप्त या अक्षम कोड 410 लौटाता है; एक अज्ञात कोड 404 लौटाता है। रीड्स expires_at की जांच करते हैं, जबकि एसिंक्रोनस विलोपन केवल स्टोरेज को पुनः प्राप्त करता है।
  • किस रीडायरेक्ट स्थिति की अपेक्षा है? डिफ़ॉल्ट रूप से 302 का उपयोग करें क्योंकि मैपिंग अक्षम हो सकती हैं और सेवा को नीति या एनालिटिक्स के लिए प्रत्येक अनुरोध की आवश्यकता हो सकती है। 301 केवल उन अपरिवर्तनीय लिंक के लिए ऑफ़र करें जिनके स्वामी दीर्घकालिक क्लाइंट और मध्यवर्ती कैशिंग स्वीकार करते हैं।
  • किस संगति (consistency) की आवश्यकता है? कोड आरक्षण और कस्टम-उपनाम निर्माण के लिए मजबूत विशिष्टता की आवश्यकता होती है। मौजूदा रीडायरेक्ट उपलब्धता के पक्ष में हैं, लेकिन एक सफल निर्माण कैश पॉपुलेशन या रीड-आफ्टर-राइट पाथ के माध्यम से तुरंत पढ़ने योग्य होना चाहिए।
  • क्या एनालिटिक्स दोषरहित (lossless) होना चाहिए? यह बेस पाथ के बाहर है। यदि जोड़ा जाता है, तो स्वीकार्य हानि और ताजगी को अलग से परिभाषित करें ताकि एक विलंबित एनालिटिक्स पाइपलाइन रीडायरेक्ट को अवरुद्ध न करे।
  • क्या सेवा गंतव्य सामग्री प्राप्त (fetch) करती है? रीडायरेक्ट पाथ ऐसा नहीं करता है। कोई भी पूर्वावलोकन या मैलवेयर स्कैनर जो URLs प्राप्त करता है, SSRF सुरक्षा के साथ एक पृथक एसिंक्रोनस सेवा में चलता है।

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

“मैं निर्माण और रीडायरेक्शन को दो मुख्य प्रवाह के रूप में रखूँगा। प्रति दिन एक मिलियन निर्माण और एक सौ मिलियन रीडायरेक्ट के साथ, औसत लगभग 12 राइट्स और 1,200 रीड्स प्रति सेकंड है, जिसमें 10-गुना पीक्स शामिल हैं। मैं क्रिप्टोग्राफ़िक रूप से रैंडम आठ-वर्ण वाले Base62 कोड जनरेट करूँगा और उन्हें एक परमाणु इन्सर्ट-इफ-एब्सेंट (insert-if-absent) के साथ आरक्षित करूँगा; कस्टम उपनाम समान स्थिति का उपयोग करते हैं। ड्यूरेबल मैपिंग स्टोर कोड के हैश द्वारा विभाजित (partitioned) होता है और सत्य का स्रोत बना रहता है। रीडायरेक्ट सर्वर कैश-असाइड (cache-aside) का उपयोग करते हैं, स्थिति और समाप्ति की जांच करते हैं, फिर 302 Location प्रतिक्रिया लौटाते हैं। निर्माण idempotent है, कैश प्रविष्टियाँ कभी भी लिंक समाप्ति से अधिक जीवित नहीं रहती हैं, और अपडेट या टेकडाउन अमान्यीकरण को पुश करते हैं। मैं हॉट रीड पाथ को स्वतंत्र रूप से स्केल करूँगा, कैश मिस को स्टैम्पेड से बचाऊँगा, और एनालिटिक्स को एसिंक्रोनस रखूँगा। मैं स्पष्ट SLOs के विरुद्ध विशिष्टता दौड़ (uniqueness races), प्रतिक्रिया-हानि पुनः प्रयास, हॉट कीज, कैश और डेटाबेस विफलताओं, समाप्ति सीमाओं और दुरुपयोग-अक्षम प्रसार को मान्य करूँगा।”

चरण-दर-चरण विस्तृत विवरण

एक छोटे क्षमता लेज़र (capacity ledger) से शुरुआत करें:

text
Creates:   1,000,000 / 86,400 ≈ 12/s average, ≈ 120/s at 10x peak
Redirects: 100,000,000 / 86,400 ≈ 1,200/s average, ≈ 12,000/s at 10x peak
Mappings:  1,000,000 × 365 × 5 = 1.825 billion
Raw data:  1.825 billion × 500 bytes ≈ 0.9 TB before overhead and replicas
Code space: 62^8 = 218,340,105,584,896; occupancy remains below 0.001%

कोर API संकीर्ण रह सकता है:

text
POST /v1/links
Idempotency-Key: client-generated-key
{ "url": "https://example.com/a", "customAlias": null, "expiresAt": null }
-> 201 { "code": "aZ3kP9qR", "shortUrl": "https://sho.rt/aZ3kP9qR" }

GET /{code}
-> 302 Location: https://example.com/a
-> 404 when the code never existed
-> 410 when it is expired or disabled

प्राथमिक एक्सेस पैटर्न कोड द्वारा एक बिंदु लुकअप (point lookup) है, इसलिए एक ड्यूरेबल रिकॉर्ड को केवल उन फ़ील्ड्स की आवश्यकता होती है जो निर्माण, रीडायरेक्शन और लाइफ़साइकिल नीति की सेवा करते हैं:

text
links
  code          primary key
  long_url
  owner_id
  status        ACTIVE | DISABLED
  created_at
  expires_at    nullable
  version

create_requests
  owner_id + idempotency_key    unique key
  request_fingerprint
  code
  status
  expires_at

आठ Base62 वर्णों के लिए क्रिप्टोग्राफ़िक रूप से सुरक्षित रैंडम जनरेटर का उपयोग करें। सात-वर्ण वाले स्थान में पहले से ही लगभग 3.5 ट्रिलियन मान होते हैं, लेकिन आठवाँ वर्ण अधिक हेडरूम छोड़ता है और नगण्य URL लागत पर ऑनलाइन गणना (online enumeration) को कठिन बनाता है। एक रैंडम जनरेटर एक केंद्रीकृत संख्यात्मक एलोकेटर और पूर्वानुमेय अनुक्रमों से बचता है। इसे अभी भी एक परमाणु सशर्त राइट की आवश्यकता है: मैपिंग केवल तभी डालें जब code अनुपस्थित हो। यदि जनरेट किए गए कोड के लिए शर्त विफल हो जाती है, तो सीमित पुनः प्रयास गणना के साथ फिर से ड्रा करें। यदि कोई कस्टम उपनाम टकराता है, तो 409 लौटाएं क्योंकि इसे बदलने से कॉलर के अनुबंध का उल्लंघन होगा।

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

निर्माण इस क्रम में आगे बढ़ता है:

  1. जहां आवश्यक हो वहां प्रमाणित करें, कॉलर को दर-सीमित (rate-limit) करें, URL को पार्स करें, केवल http और https की अनुमति दें, लंबाई और नीति सीमाओं को लागू करें, और कस्टम उपनाम को सामान्य करें (normalize)।
  2. Idempotency कुंजी की जाँच करें। एक अलग अनुरोध फ़िंगरप्रिंट के साथ इसका पुन: उपयोग करना एक विरोध है; उसी अनुरोध के साथ इसका पुन: उपयोग मूल परिणाम लौटाता है।
  3. एक कोड जनरेट करें या स्वीकार करें। एक लेन-देन में, सशर्त रूप से कोड आरक्षित करें और idempotency रिकॉर्ड को बनाए रखें। लेन-देन दो रचनाकारों को एक ही उपनाम जीतने से रोकता है और एक खोई हुई प्रतिक्रिया को पुनः प्रयास पर एक अलग लिंक बनाने से रोकता है।
  4. ड्यूरेबल कमिट के बाद, कैश स्थिति को पॉप्युलेट या अमान्य करें और एसिंक्रोनस प्रतिष्ठा स्कैनिंग को कतारबद्ध करें। कभी भी ऐसा कोड न लौटाएं जो केवल कैश में मौजूद हो।

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

रीडायरेक्शन के लिए, एक एज या स्टेटलेस रीडायरेक्ट सेवा तेजी से प्रचारित डिनाइलिस्ट की जांच करती है, फिर वितरित कैश में code की तलाश करती है। एक हिट अभी भी status और expires_at की जांच करती है। एक मिस ड्यूरेबल स्टोर से पॉइंट रीड करता है, उन्हीं लाइफ़साइकिल फ़ील्ड्स को मान्य करता है, और मैपिंग को कैश करता है। कैश TTL को expires_at से बाद का न सेट करें; व्यापक TTLs में थोड़ा जिटर (jitter) जोड़ें ताकि कई प्रविष्टियाँ एक साथ समाप्त न हों। स्कैन को अवशोषित करने के लिए अज्ञात कोड को संक्षेप में कैश करें, लेकिन उस कोड के साथ एक कस्टम उपनाम बनाए जाने पर नकारात्मक प्रविष्टि को अमान्य करें।

डिफ़ॉल्ट रूप से Location हेडर के साथ 302 लौटाएं। HTTP सिमेंटिक्स 302 को एक अस्थायी स्थान के रूप में परिभाषित करता है, इसलिए क्लाइंट भविष्य के अनुरोधों पर छोटे URL का उपयोग करना जारी रखते हैं। 301 एक स्थायी नए URI को इंगित करता है और अनुमानी रूप से (heuristically) कैश करने योग्य है; यह सेवा से ट्रैफ़िक को हटा सकता है लेकिन निरसन (revocation), गंतव्य परिवर्तन और अनुरोध-स्तरीय एनालिटिक्स में भी देरी करता है। रीडायरेक्ट स्थिति और Cache-Control उत्पाद अनुबंध हैं, न कि सेवा के अंदर छिपा हुआ प्रदर्शन टॉगल।

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

विफलता नीति को सत्य-के-स्रोत सीमा को संरक्षित करना चाहिए:

  • यदि कैश अनुपलब्ध है, तो सर्किट ब्रेकर, सीमित डायरेक्ट रीड्स, स्थानीय हॉट प्रविष्टियों और प्रवेश नियंत्रण (admission control) का उपयोग करें। अनबाउंडेड कैश बाईपास एक कैश घटना को डेटाबेस घटना में बदल सकता है।
  • यदि डेटाबेस रीड पाथ अनुपलब्ध है, तो केवल तभी सीमित बासी सकारात्मक कैश प्रविष्टि (bounded stale positive cache entry) की सेवा करें जब उत्पाद उस जोखिम को स्वीकार करता है। कभी भी समाप्त हो चुके लिंक को न बढ़ाएं या टेकडाउन डिनाइलिस्ट को बायपास न करें।
  • यदि ड्यूरेबल राइट पाथ विशिष्टता की गारंटी नहीं दे सकता है, तो निर्माण को विफल करें। उपलब्धता एक कोड के लिए दो गंतव्य जारी करने को उचित नहीं ठहराती है।
  • यदि एनालिटिक्स में देरी होती है, तो रीडायरेक्ट जारी रहते हैं और अलग से बताए गए एनालिटिक्स अनुबंध के अनुसार क्लिक इवेंट बफर, नमूना या ड्रॉप होते हैं।
  • यदि क्लीनअप रुक जाता है, तो रीड्स अभी भी समाप्ति लागू करते हैं। स्टोरेज बढ़ता है, लेकिन समाप्त लिंक की सेवा नहीं की जाती है।

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

सत्यापन को गुणों और विफलताओं का परीक्षण करना चाहिए। एक कस्टम उपनाम के लिए कई रचनाकारों को प्रतिस्पर्धा कराएं और पुष्टि करें कि वास्तव में केवल एक सफल होता है। पहली POST प्रतिक्रिया खोएं और पुष्टि करें कि idempotent पुनः प्रयास वही कोड लौटाता है। समाप्ति से एक सेकंड पहले, उस पर और उसके बाद परीक्षण करें। नकारात्मक-कैश लुकअप के तुरंत बाद एक कोड बनाएं। सशर्त विरोधों का कृत्रिम रूप से परीक्षण करने के लिए पर्याप्त रैंडम कोड जनरेट करें। एक व्यापक कार्य सेट और एक एकल हॉट कोड दोनों के साथ 10-गुना पीक लोड करें, फिर कैश नोड्स को विफल करें, डेटाबेस को थ्रॉटल करें, अमान्यीकरण में देरी करें, और क्लीनअप और एनालिटिक्स कार्यकर्ताओं को रोकें। केवल औसत थ्रूपुट की रिपोर्ट करने के बजाय रीडायरेक्ट सफलता, p99 लेटेंसी, कैश हिट दर, डेटाबेस मिस लोड, सशर्त विरोध, बासी-लिंक सेवा और टेकडाउन प्रसार को मापें।

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

“मैं बेस सिस्टम को वैकल्पिक कस्टम उपनाम और समाप्ति के साथ शॉर्ट लिंक बनाने और रिज़ॉल्व करने के लिए सीमित करूँगा। मैं स्पष्ट करूँगा कि गंतव्य अपरिवर्तनीय हैं, समान लंबे URLs को अलग-अलग कोड प्राप्त हो सकते हैं, ज्ञात समाप्त लिंक 410 लौटाते हैं, और एनालिटिक्स रीडायरेक्ट को अवरुद्ध नहीं करता है।

केस मान्यताओं का उपयोग करते हुए, निर्माण औसतन लगभग 12 अनुरोध प्रति सेकंड और 120 के करीब पीक होता है; रीडायरेक्ट औसतन लगभग 1,200 और पीक लगभग 12,000 होता है। पाँच वर्षों में लगभग 1.8 बिलियन मैपिंग, या 500 बाइट्स प्रत्येक पर लगभग 0.9 TB कच्चा डेटा रहता है। इसलिए मैं एक ऐसे ड्यूरेबल स्टोर का उपयोग करूँगा जो पॉइंट रीड्स, पार्टिशनिंग, रेप्लिकेशन और परमाणु सशर्त इंसर्ट का समर्थन करता है, जिसमें विभाजन कुंजी (partition key) के रूप में code होगा।

जनरेट किए गए लिंक के लिए, मैं क्रिप्टोग्राफ़िक रैंडमनेस के साथ आठ-वर्ण वाला Base62 कोड तैयार करूँगा। स्थान लगभग 218 ट्रिलियन मानों का है, इसलिए हमारे पैमाने पर प्रति-इन्सर्ट कोलिजन की संभावना बहुत कम रहती है, लेकिन रैंडमनेस विशिष्टता को साबित नहीं करती है। मैं इन्सर्ट-इफ-एब्सेंट के साथ कोड आरक्षित करता हूँ और जनरेट किए गए कोलिजन का पुनः प्रयास करता हूँ। एक कस्टम-उपनाम विरोध 409 लौटाता है। POST में एक idempotency कुंजी भी होती है; मैपिंग और अनुरोध रिकॉर्ड एक साथ कमिट होते हैं ताकि खोई हुई प्रतिक्रिया वही कोड लौटा सके।

रीडायरेक्ट सेवा एक टेकडाउन डिनाइलिस्ट और कैश की जांच करती है। कैश मिस होने पर यह पॉइंट रीड करता है, सक्रिय स्थिति और समाप्ति की जांच करता है, शेष जीवनकाल से अधिक कैश नहीं करता है, और Location के साथ 302 लौटाता है। मैं डिफ़ॉल्ट रूप से 302 का उपयोग करता हूँ क्योंकि मैपिंग अक्षम हो सकती है और सेवा को अनुरोध-स्तरीय नीति या एनालिटिक्स की आवश्यकता हो सकती है; अपरिवर्तनीय लिंक 301 और मजबूत कैशिंग का विकल्प चुन सकते हैं। नकारात्मक प्रविष्टियों को संक्षिप्त TTLs मिलते हैं, और एक कस्टम उपनाम बनाने से कोई भी नकारात्मक कैश प्रविष्टि अमान्य हो जाती है।

ड्यूरेबल मैपिंग सत्य का स्रोत है। कैश विफलता प्रवेश नियंत्रण के साथ सीमित डेटाबेस रीड्स में बदल जाती है, डेटाबेस विफलता केवल नीति के तहत सीमित बासी सकारात्मक प्रविष्टियों का उपयोग कर सकती है, और यदि विशिष्टता की गारंटी नहीं दी जा सकती है तो निर्माण विफल हो जाता है। हॉट कीज लेयर्ड कैशिंग और मिस कोलेसिंग का उपयोग करती हैं। एनालिटिक्स और प्रतिष्ठा स्कैनिंग एसिंक्रोनस हैं, जबकि पुष्ट दुरुपयोग तेजी से प्रचारित नियंत्रण पाथ के माध्यम से लिंक को अक्षम कर देता है।

मैं समवर्ती उपनाम दौड़ों, प्रतिक्रिया-हानि पुनः प्रयासों, समाप्ति सीमाओं, नकारात्मक-कैश अमान्यीकरण, हॉट-की और व्यापक-सेट लोड, कैश हानि, डेटाबेस थ्रॉटलिंग, क्लीनअप विफलता और टेकडाउन प्रसार के साथ डिज़ाइन को साबित करूँगा। स्वीकृति 99.99% रीडायरेक्ट उपलब्धता, बताए गए पीक के तहत 100 ms से नीचे p99, कोई डुप्लिकेट कोड विजेता नहीं, कोई समाप्त लिंक सेवा नहीं, और एक मापे गए अक्षम प्रसार विंडो से बंधी है।”

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

  • लंबे URL को हैश करना और विशिष्टता मान लेना → ट्रंकेशन टकराता है और समान URLs को अलग-अलग नीतियों की आवश्यकता हो सकती है → एक परमाणु आरक्षण का उपयोग करें और परिभाषित करें कि क्या डिडुप्लीकेशन वांछित है।
  • सशर्त राइट के बिना रैंडम कोड का उपयोग करना → संभावना को गारंटी समझने की भूल की जाती है → केवल तभी इन्सर्ट करें जब कोड अनुपस्थित हो और जनरेट किए गए कोलिजन का पुनः प्रयास करें।
  • राइट टाइमआउट के बाद एक नया कोड लौटाना → एक क्लाइंट क्रिया कई लिंक बनाती है → पुनः प्रयासों को एक बने हुए idempotency कुंजी से बांधें और मूल परिणाम को पुनर्प्राप्त करें।
  • ड्यूरेबल स्टोरेज से पहले कैश लिखना → एक सफल दिखने वाला लिंक निष्कासन (eviction) पर गायब हो जाता है → पहले सत्य के स्रोत को कमिट करें, फिर कैश पॉप्युलेट करें।
  • समाप्ति के लिए विलोपन कार्य पर निर्भर रहना → एक विलंबित कार्य समाप्त लिंक की सेवा करता है → प्रत्येक रिज़ॉल्यूशन पाथ पर expires_at की जांच करें और स्थान पुनः प्राप्त करने के लिए केवल क्लीनअप का उपयोग करें।
  • 301 को "तेज़" और 302 को "अनकैश्ड" कहना → कैश व्यवहार और परिवर्तनशीलता को अत्यधिक सरल बना दिया जाता है → उत्पाद अनुबंध से रीडायरेक्ट सिमेंटिक्स और स्पष्ट कैश नियंत्रण चुनें।
  • 404 को अनिश्चित काल तक कैश करना → एक नया बनाया गया कस्टम उपनाम दुर्गम बना रहता है → एक छोटे नकारात्मक TTL का उपयोग करें और निर्माण पर इसे अमान्य करें।
  • प्रत्येक कैश मिस को सीधे डेटाबेस पर भेजना → एक हॉट-की समाप्ति भगदड़ (stampede) पैदा करती है → अनुरोध कोलेसिंग, TTL जिटर और लेयर्ड हॉट-की कैशिंग का उपयोग करें।
  • एनालिटिक्स को सिंक्रोनस बनाना → एक गैर-कोर पाइपलाइन आउटेज रीडायरेक्ट को तोड़ता है → रिज़ॉल्व करने के बाद इवेंट्स उत्सर्जित करें और एनालिटिक्स हानि/ताजगी को अलग से परिभाषित करें।
  • शॉर्ट कोड को प्राधिकरण के रूप में मानना → गणना या साझाकरण संरक्षित सामग्री को उजागर करता है → गंतव्य पर प्राधिकरण की आवश्यकता होती है और कोड का उपयोग केवल लोकेटर के रूप में करें।

फॉलो-अप्स और उन्हें कैसे संभालें

फॉलो-अप 1: आप निकट-वास्तविक समय (near-real-time) क्लिक एनालिटिक्स कैसे जोड़ेंगे?

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

फॉलो-अप 2: आप क्षेत्रों में एक्टिव-एक्टिव कैसे तैनात करेंगे?

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

फॉलो-अप 3: संपादन योग्य गंतव्यों के लिए क्या परिवर्तन होते हैं?

वर्ज़न्ड सशर्त अपडेट, एक ऑडिट रिकॉर्ड, स्वामी प्राधिकरण, और कोड और वर्ज़न द्वारा कुंजीबद्ध कैश अमान्यीकरण जोड़ें। परिभाषित करें कि क्या पहले से कैश की गई 301 प्रतिक्रियाएं बासी रह सकती हैं; यदि त्वरित संपादन या निरसन मायने रखता है, तो सीमित कैश ताजगी के साथ 302 को डिफ़ॉल्ट करें। समवर्ती अपडेट के लिए एक अपेक्षित वर्ज़न की आवश्यकता होती है ताकि एक संपादक चुपचाप दूसरे को अधिलेखित (overwrite) न करे।

फॉलो-अप 4: आप प्रति सेकंड लाखों अनुरोध प्राप्त करने वाले एक लिंक को कैसे संभालते हैं?

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

फॉलो-अप 5: कस्टम डोमेन कुंजी और रूटिंग मॉडल को कैसे प्रभावित करते हैं?

विशिष्टता केवल code नहीं, बल्कि (domain, code) बन जाती है। डोमेन स्वामित्व सत्यापित करें, प्रमाणपत्र प्रदान करें, होस्ट द्वारा रूट करें, और टेनेंट कोटा और दुरुपयोग नीति रखें। कैश कुंजी और डेटाबेस विभाजन कुंजी में डोमेन शामिल होना चाहिए। यदि एक ही उपनाम दो डोमेन पर मौजूद है, तो किसी को भी दूसरे को अधिलेखित या अमान्य नहीं करना चाहिए।

फॉलो-अप 6: क्या होगा यदि कानूनी विलोपन द्वारा किसी गंतव्य को तुरंत मिटाना आवश्यक हो?

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

फॉलो-अप 7: आप आठ-वर्ण से लंबे कोड में कैसे माइग्रेट करेंगे?

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

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

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

संबंधित इंटरव्यू टूल

सिस्टम डिज़ाइन उत्तर के लिए हल करें का उपयोग करें

पहले आवश्यकताओं को स्पष्ट करें, फिर स्केल, आर्किटेक्चर, कंपोनेंट चयन और ट्रेड-ऑफ की ओर बढ़ें।

टूल देखें