मैं दो नोड्स के बीच आपसी संबंध के दौरान एक वितरित गतिरोध से कैसे बच सकता हूं?


11

मान लें कि हमारे पास दो सहकर्मी नोड हैं: पहला नोड दूसरे को कनेक्शन अनुरोध भेज सकता है, लेकिन दूसरा भी पहले वाले को कनेक्शन अनुरोध भेज सकता है। दो नोड्स के बीच दोहरे संबंध से कैसे बचें? इस समस्या को हल करने के लिए, इनबाउंड या आउटबाउंड टीसीपी कनेक्शन बनाने के लिए प्रदर्शन किए गए अनुक्रमिक बनाने के लिए पर्याप्त होगा।

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

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

  • पहला नोड दूसरे को कनेक्शन अनुरोध भेज सकता है;
  • दूसरा नोड पहले वाले को कनेक्शन अनुरोध भेज सकता है;
  • यह मानते हुए कि दो कनेक्शन अनुरोध अतुल्यकालिक नहीं हैं, दोनों नोड्स आने वाले कनेक्शन अनुरोधों को लॉक करते हैं।

मैं इस समस्या को कैसे हल कर सकता हूं?

अद्यतन: हालांकि, मुझे अभी भी सूची पर हर बार एक नया (आवक या आउटगोइंग) कनेक्शन बनाया जाता है, क्योंकि अन्य धागे इस सूची तक पहुंच सकते हैं, फिर भी गतिरोध की समस्या बनी रहेगी।

अद्यतन 2: आपकी सलाह के आधार पर मैंने लॉगिन अनुरोध की पारस्परिक स्वीकृति को रोकने के लिए एक एल्गोरिथ्म लिखा। चूंकि प्रत्येक नोड एक सहकर्मी है, इसलिए नए कनेक्शन अनुरोध भेजने और आने वाले कनेक्शनों को स्वीकार करने के लिए सर्वर रूटीन के लिए ग्राहक की दिनचर्या हो सकती है ।

ClientSideLoginRoutine() {
    for each (address in cache) {
        lock (neighbors_table) {
            if (neighbors_table.contains(address)) {
                // there is already a neighbor with the same address
                continue;
            }
            neighbors_table.add(address, status: CONNECTING);

        } // end lock

        // ...
        // The node tries to establish a TCP connection with the remote address
        // and perform the login procedure by sending its listening address (IP and port).
        boolean login_result = // ...
        // ...

        if (login_result)
            lock (neighbors_table)
                neighbors_table.add(address, status: CONNECTED);

    } // end for
}

ServerSideLoginRoutine(remoteListeningAddress) {
    // ...
    // initialization of data structures needed for communication (queues, etc)
    // ...

    lock(neighbors_table) {
        if(neighbors_table.contains(remoteAddress) && its status is CONNECTING) {
            // In this case, the client-side on the same node has already
            // initiated the procedure of logging in to the remote node.

            if (myListeningAddress < remoteListeningAddress) {
                refusesLogin();
                return;
            }
        }
        neighbors_table.add(remoteListeningAddress, status: CONNECTED);

    } // end lock
}

उदाहरण: IP: नोड A का पोर्ट A: 7001 है - IP: नोड B का पोर्ट B: 8001 है।

मान लीजिए कि नोड ए ने नोड बी: 8001 पर एक लॉगिन अनुरोध भेजा है। इस मामले में, नोड ए अपने स्वयं के सुनने के पते (ए: 7001) भेजकर लॉगिन दिनचर्या कहता है। परिणामस्वरूप, पड़ोसी A के नोड A में दूरस्थ नोड (B: 8001) का पता होता है: यह पता CONNECTING स्थिति से संबद्ध है। नोड ए, नोड बी के लिए प्रतीक्षा कर रहा है या लॉगिन अनुरोध को अस्वीकार कर सकता है।

इस बीच, नोड बी ने नोड ए (ए: 7001) के पते पर एक कनेक्शन अनुरोध भेजा है, तो नोड ए नोड बी के अनुरोध को संसाधित कर सकता है। इसलिए, नोड बी के पड़ोसियों_योग्य में रिमोट का पता शामिल है नोड (ए: 7001): यह पता कनेक्शन स्थिति के साथ जुड़ा हुआ है। नोड बी नोड ए के लिए प्रतीक्षा कर रहा है या लॉगिन अनुरोध को अस्वीकार कर सकता है।

यदि नोड ए का सर्वर पक्ष बी: 8001 से अनुरोध को अस्वीकार करता है, तो मुझे यह सुनिश्चित करना चाहिए कि नोड बी का सर्वर पक्ष ए: 7001 से अनुरोध को स्वीकार करेगा। इसी प्रकार, यदि नोड B का सर्वर पक्ष A: 7001 से अनुरोध को अस्वीकार करता है, तो मुझे यह सुनिश्चित करना चाहिए कि नोड A का सर्वर पक्ष B: 8001 से अनुरोध स्वीकार करेगा।

के अनुसार "छोटे पता" नियम , इस मामले में नोड ए, नोड बी द्वारा लॉगिन अनुरोध को अस्वीकार करते हुए नोड बी नोड ए से अनुरोध स्वीकार करेगा

तुम उसके बारे में क्या सोचते हो?


इस प्रकार के एल्गोरिदम विश्लेषण और साबित करने के लिए बहुत कठिन हैं। हालांकि, एक शोधकर्ता है जो वितरित कंप्यूटिंग के एक महान कई पहलुओं में विशेषज्ञ है। लेस्ली लामपोर्ट के प्रकाशन पृष्ठ पर देखें: research.microsoft.com/en-us/um/people/lamport/pubs/pubs.html
DeveloperDon

जवाबों:


3

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


हालाँकि, मुझे अभी भी सूची पर हर बार एक नया (इनकमिंग या आउटगोइंग) कनेक्शन बनाया जाता है, क्योंकि अन्य धागे इस सूची तक पहुंच सकते हैं, फिर भी गतिरोध की समस्या बनी रहेगी।
enzom83

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

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

1
@ enzom83 जब तक आप महत्वपूर्ण खंड के भीतर से कनेक्शन का अनुरोध नहीं करते हैं, तब तक आपको वितरित गतिरोध नहीं मिलेगा। आशावादी दृष्टिकोण के पीछे यह विचार है - आप केवल नोड को जोड़ने या निकालने के लिए सूची पर एक ताला लगाते हैं, और यदि आप एक नोड जोड़ते समय एक पारस्परिक संबंध पाते हैं, तो आप "छोटे पते" का उपयोग करके महत्वपूर्ण अनुभाग को छोड़ने के बाद इसे तोड़ देते हैं शासन (उत्तर से)।
dasblinkenlight

4

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

समय 1: A, B से जुड़ने का प्रयास करता है, संख्या 123 भेजता है।

समय 2: बी ए से जुड़ने की कोशिश करता है, नंबर 234 भेजता है।

समय 3: बी को ए का अनुरोध प्राप्त होता है। चूँकि B के स्वयं के अनुरोध की संख्या अधिक है, इसलिए यह A के अनुरोध को अस्वीकार करता है।

समय 4: A को B का अनुरोध प्राप्त होता है। चूंकि बी के अनुरोध में एक उच्च संख्या है, ए इसे स्वीकार करता है और अपने स्वयं के अनुरोध को छोड़ देता है।

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

यादृच्छिक संख्याओं के बजाय, आप समय से पहले नंबर भी वितरित कर सकते हैं (अर्थात 1 से n तक की सभी मशीनों को नंबर दें), या मैक पते का उपयोग करें, या नंबर खोजने का कोई अन्य तरीका जहां टक्कर की संभावना इतनी कम हो अनदेखा करने योग्य।


3

अगर मैं समझता हूं, तो आप जिस समस्या से बचने की कोशिश कर रहे हैं, वह इस प्रकार है:

  • नोड 2 नोड 2 से कनेक्शन का अनुरोध करता है
  • Node1 कनेक्शन सूची को लॉक करता है
  • नोड 1 से नोड 2 कनेक्शन का अनुरोध करता है
  • Node2 कनेक्शन सूची को लॉक करता है
  • नोड 2 को नोड 1 से कनेक्शन अनुरोध प्राप्त होता है, क्योंकि सूची बंद है
  • नोड 1 को नोड 2 से कनेक्शन अनुरोध प्राप्त होता है, अस्वीकार कर दिया जाता है क्योंकि सूची बंद है
  • न ही कोई एक दूसरे से जुड़ता है।

मैं इससे निपटने के लिए कुछ अलग तरीके सोच सकता हूं।

  1. यदि आप नोड से कनेक्ट करने का प्रयास करते हैं, और यह "सूची लॉक" संदेश के साथ आपके अनुरोध को अस्वीकार कर देता है, तो दोबारा कोशिश करने से पहले मिलीसेकंड की एक यादृच्छिक संख्या की प्रतीक्षा करें। (यादृच्छिकता महत्वपूर्ण है। यह बहुत कम संभावना है कि दोनों समय की एक ही राशि के लिए प्रतीक्षा करेंगे और एक ही समस्या विज्ञापन infinitum दोहराएंगे ।)
  2. एक समय सर्वर के साथ दोनों सिस्टम की घड़ियों को सिंक्रनाइज़ करें, और कनेक्शन अनुरोध के साथ टाइमस्टैम्प भेजें। यदि एक कनेक्शन अनुरोध एक नोड से आता है जिसे आप वर्तमान में कनेक्ट करने का प्रयास कर रहे हैं, तो दोनों नोड्स सहमत हैं कि जो भी पहले जीत को जोड़ने की कोशिश करता है, और दूसरा कनेक्शन बंद हो जाता है।

समस्या यह भी है कि अनुरोध प्राप्त करने वाले नोड कनेक्शन को अस्वीकार नहीं कर सकते हैं, लेकिन यह सूची पर ताला लगाने के लिए अनिश्चित काल तक प्रतीक्षा में रहेगा।
enzom83
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.