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

कोडिंग साक्षात्कार: डिलीशन के साथ Cuckoo Filter लागू करना

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

प्रश्न

add, mightContain और remove के साथ एक Cuckoo Filter लागू करें। इसे डिलीशन का समर्थन करते हुए सीमित मेमोरी में अनुमानित सदस्यता क्वेरीज़ प्रदान करनी चाहिए। समझाएं कि आप दो संभावित बकेट्स की गणना कैसे करते हैं, फ़िंगरप्रिंट्स कैसे स्टोर करते हैं, रीलोकेशन के साथ भरे हुए बकेट को कैसे संभालते हैं, फ़ाल्स पॉज़िटिव्स से परे त्रुटियों से कैसे बचते हैं, और इंसर्शन विफलता या रीसाइज़िंग पर कैसे प्रतिक्रिया देते हैं।

प्रॉम्प्ट और संदर्भ

Cuckoo Filter एक अनुमानित सदस्यता संरचना (approximate membership structure) है: false का अर्थ है कि तत्व निश्चित रूप से अनुपस्थित है, जबकि true का अर्थ है कि यह उपस्थित हो सकता है। एक मानक Bloom Filter की तुलना में, यह बकेट्स में छोटे फ़िंगरप्रिंट स्टोर करता है ताकि यह डिलीशन और लचीले लुकअप का समर्थन कर सके; इसका ट्रेड-ऑफ यह है कि इंसर्शन प्रविष्टियों को स्थानांतरित (relocate) कर सकता है और क्षमता के करीब विफल हो सकता है। यह समस्या हैशिंग, ऐरे लेआउट, रैंडमाइज़ेशन, एज हैंडलिंग और बेंचमार्किंग का परीक्षण करती है।

साक्षात्कारकर्ता क्या मूल्यांकन कर रहा है

  • क्या आप एक फ़िंगरप्रिंट और दो संभावित बकेट्स के बीच संबंध को समझा सकते हैं।
  • क्या निष्कासन (removal) फ़ाल्स नेगेटिव्स से बचाता है और लूप्स को रोकने के लिए रीलोकेशन सीमित (bounded) है।
  • क्या आप डुप्लिकेट ऑपरेशन्स, भरे हुए बकेट्स, हैश कोलिज़न और कॉनकरेंसी सीमाओं को संभालते हैं।
  • क्या आप क्षमता, फ़िंगरप्रिंट बिट्स और फ़ाल्स-पॉज़िटिव लक्ष्य का उपयोग करके पैरामीटर्स का चयन और सत्यापन करते हैं।

पहले पूछने के लिए स्पष्टीकरण प्रश्न

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

30-सेकंड का उत्तर ढांचा

प्रत्येक मान के लिए मैं एक गैर-शून्य फ़िंगरप्रिंट f और एक प्राथमिक बकेट i1 की गणना करूँगा, फिर फ़िंगरप्रिंट से एक दूसरा बकेट i2 प्राप्त करूँगा ताकि f ठीक दो संभावित बकेट्स में रह सके। लुकअप दोनों बकेट्स की जांच करता है; निष्कासन केवल एक मेल खाने वाले फ़िंगरप्रिंट को हटाता है, Bloom Filter में साझा बिट्स को साफ़ करने के विपरीत। इंसर्शन पहले किसी भी बकेट का प्रयास करता है, फिर दोनों भरे होने पर सीमित यादृच्छिक रीलोकेशन करता है। किक सीमा तक पहुँचने पर विफलता मिलती है और यह पुनर्निर्माण या किसी अन्य स्तर को ट्रिगर करता है। फ़िंगरप्रिंट लंबाई, बकेट क्षमता और अधिकतम लोड को फ़ाल्स-पॉज़िटिव, इंसर्शन-सफलता और लेटेंसी परीक्षणों के साथ कैलिब्रेट किया जाना चाहिए।

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

1. इंटरफ़ेस और इनवेरिएंट्स को परिभाषित करें

एक सफल add(x) के बाद, इसका फ़िंगरप्रिंट दो संभावित बकेट्स में से एक में होना चाहिए। mightContain(x) केवल तभी false लौटाता है जब किसी भी बकेट में f न हो; remove(x) केवल एक मेल खाने वाले फ़िंगरप्रिंट को साफ़ करता है। यदि दो मान एक फ़िंगरप्रिंट साझा करते हैं, तो एक को हटाने पर दूसरा true लौटा सकता है, जो एक स्वीकार्य फ़ाल्स पॉज़िटिव है, लेकिन इन्सर्ट किया गया मान कभी भी false नहीं बनना चाहिए।

2. फ़िंगरप्रिंट्स और संभावित बकेट्स उत्पन्न करें

एक स्थिर एन्कोडिंग से प्राथमिक इंडेक्स i1 की गणना करें, फिर एक निश्चित लंबाई का गैर-शून्य फ़िंगरप्रिंट f लें। i2 = i1 XOR hash(f) प्राप्त करें और इसे बकेट काउंट द्वारा मॉड्यूलो करें। इंडेक्स और फ़िंगरप्रिंट गणना में हैश एल्गोरिदम, सीड, बाइट क्रम और वर्ज़न तय होना चाहिए; अन्यथा पर्सिस्ट की गई प्रविष्टियाँ या रीसाइज़ की गई टेबलें अपठनीय हो जाती हैं। छोटे फ़िंगरप्रिंट फ़ाल्स-पॉज़िटिव दर बढ़ाते हैं, जबकि लंबे फ़िंगरप्रिंट अधिक मेमोरी की खपत करते हैं।

3. बकेट लेआउट और लुकअप डिज़ाइन करें

प्रत्येक बकेट पूर्ण मानों के बजाय फ़िंगरप्रिंट स्लॉट की एक निश्चित संख्या संग्रहीत करता है। लुकअप केवल i1 और i2 को पढ़ता है, और जब किसी में भी f शामिल होता है तो "संभवतः उपस्थित" लौटाता है। बकेट की चौड़ाई लोड और स्थानीय टकरावों (local collisions) को प्रभावित करती है। एक सन्निहित ऐरे पॉइंटर ओवरहेड को कम कर सकता है; तालिका के साथ बकेट काउंट, स्लॉट काउंट, फ़िंगरप्रिंट बिट्स और हैश वर्ज़न को पर्सिस्ट करें।

4. इंसर्शन और सीमित रीलोकेशन को संभालें

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

5. डिलीशन और डुप्लिकेट ऑपरेशन्स लागू करें

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

6. सुरक्षित रूप से परीक्षण करें, विफल हों और रीसाइज़ करें

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

मॉडल उच्च-गुणवत्ता उत्तर

मैं एक स्थिर गैर-शून्य फ़िंगरप्रिंट f और प्राथमिक बकेट i1 की गणना करूँगा, फिर i2 = i1 XOR hash(f) प्राप्त करूँगा; प्रत्येक बकेट फ़िंगरप्रिंट्स की एक निश्चित संख्या संग्रहीत करता है। लुकअप दोनों की जांच करता है और केवल तभी false लौटाता है जब f दोनों से अनुपस्थित हो। डिलीशन एक मेल खाने वाले स्लॉट को साफ़ करता है, इसलिए यह साझा बिट्स को साफ़ नहीं करता जैसा कि एक Bloom Filter करता है; यदि छोटे-फ़िंगरप्रिंट का टकराव मायने रखता है, तो सोर्स ऑफ़ ट्रुथ से परामर्श करें। इंसर्शन दोनों बकेट्स का प्रयास करता है, फिर सीमित यादृच्छिक किक्स करता है और सीमा पर विफलता लौटाता है। मैं एन्कोडिंग, हैश सीड, बकेट काउंट, स्लॉट्स और वर्ज़न तय करूँगा, डुप्लिकेट व्यवहार को परिभाषित करूँगा, और डिलीशन को इडेम्पोटेंट बनाऊँगा। परीक्षणों में डाले गए मानों के लिए कोई फ़ाल्स नेगेटिव न होना, अनुपस्थित नमूनों के फ़ाल्स पॉज़िटिव, डिलीशन, भरे हुए बकेट्स, रीलोकेशन विफलता और समवर्ती सीमाएं शामिल हैं। उच्च लोड या विफलता दर एक पुनर्निर्माण या किसी अन्य फ़िल्टर स्तर को ट्रिगर करती है।

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

  • Cuckoo Filter को एक सटीक सेट मानना और फ़ाल्स पॉज़िटिव्स को अनदेखा करना।
  • केवल एक बकेट इंडेक्स संग्रहीत करना, जिससे निकाला गया फ़िंगरप्रिंट अपना वैकल्पिक बकेट न ढूंढ सके।
  • किक सीमा को छोड़ देना और एक चक्र को अनुरोध को ब्लॉक करने की अनुमति देना।
  • शून्य फ़िंगरप्रिंट की अनुमति देना जो खाली स्लॉट से अप्रभेद्य हो।
  • डिलीशन के दौरान पूरे बकेट या गलत स्लॉट को साफ़ करना, जिससे फ़ाल्स नेगेटिव्स बनते हैं।
  • डुप्लिकेट ऑपरेशन्स, पर्सिस्टेंस वर्ज़न्स, रीसाइज़ के दौरान दोहरे रीड्स और इंसर्शन विफलता को अनदेखा करना।

फॉलो-अप प्रश्न और उत्तर

Cuckoo Filter डिलीट क्यों कर सकता है जबकि Bloom Filter आमतौर पर ऐसा नहीं कर सकता?

Cuckoo Filter एक विशिष्ट स्लॉट से एक फ़िंगरप्रिंट हटाता है। एक Bloom Filter बिट को कई मानों द्वारा साझा किया जा सकता है, इसलिए इसे साफ़ करने से दूसरा मान टूट सकता है। दोनों फ़ाल्स पॉज़िटिव लौटा सकते हैं, और सख्त डिलीशन के लिए अभी भी फ़िंगरप्रिंट टकरावों के बारे में सोचने की आवश्यकता होती है।

आप फ़िंगरप्रिंट की लंबाई और बकेट की चौड़ाई कैसे चुनते हैं?

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

क्या रीलोकेशन सीमा तक पहुँचने पर आप किसी नए आइटम को बस छोड़ (drop) सकते हैं?

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

आप थ्रेड्स के बीच लुकअप और निष्कासन को सुसंगत कैसे बनाते हैं?

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

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

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

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

कोडिंग प्रॉम्प्ट के लिए स्क्रीनशॉट का उपयोग करें

समस्या को कैप्चर करें, फिर क्रम से प्रतिबंधों (constraints), समाधान, कोड, एज केस और जटिलता पर काम करें।

टूल देखें