দুটি নোডের মধ্যে পারস্পরিক সংযোগ চলাকালীন আমি কীভাবে বিতরণ অচলাবস্থা এড়াতে পারি?


11

মনে করুন আমাদের কাছে দুটি পিয়ার নোড রয়েছে: প্রথম নোড দ্বিতীয়টির সাথে সংযোগের অনুরোধ পাঠাতে পারে, তবে দ্বিতীয়টি প্রথমটিতে একটি সংযোগের অনুরোধটি প্রেরণ করতে পারে। কীভাবে দুটি নোডের মধ্যে ডাবল সংযোগ এড়ানো যায়? এই সমস্যাটি সমাধান করার জন্য, ইনবাউন্ড বা আউটবাউন্ড টিসিপি সংযোগ তৈরির জন্য সম্পাদিত ক্রিয়াকলাপগুলি যথাযথ করা যথেষ্ট।

এর অর্থ হ'ল প্রতিটি নোড আগত সংযোগ এবং বহির্গামী সংযোগগুলির জন্য প্রতিটি নতুন সংযোগ তৈরির ক্রিয়াকলাপটি ক্রমানুসারে প্রক্রিয়া করা উচিত। এইভাবে, সংযুক্ত নোডগুলির একটি তালিকা বজায় রাখা, কোনও নোড থেকে নতুন আগত সংযোগ গ্রহণ করার আগে বা নোডের সাথে সংযোগের অনুরোধ প্রেরণের আগে, এই নোডটি তালিকায় ইতিমধ্যে উপস্থিত কিনা তা খতিয়ে দেখতে যথেষ্ট হবে।

সংযোগ তৈরির ক্রম ক্রিয়াকলাপ করার জন্য , সংযুক্ত নোডগুলির তালিকায় একটি লক সম্পাদন করা যথেষ্ট : বাস্তবে, প্রতিটি নতুন সংযোগের জন্য, এই তালিকায় নতুন সংযুক্ত নোডের সনাক্তকারী যুক্ত করা হয়। তবে আমি ভাবছি যে এই পদ্ধতির কারণে বিতরণকৃত অচলাবস্থা সৃষ্টি হতে পারে :

  • প্রথম নোড দ্বিতীয়টিতে সংযোগের অনুরোধ পাঠাতে পারে;
  • দ্বিতীয় নোড প্রথমটির সাথে সংযোগের অনুরোধ পাঠাতে পারে;
  • ধরে নিলাম যে দুটি সংযোগের অনুরোধগুলি তাত্পর্যপূর্ণ নয়, উভয় নোডই আগত সংযোগের যে কোনও অনুরোধ লক করে lock

আমি কীভাবে এই সমস্যার সমাধান করতে পারি?

আপডেট: তবে, এখনও প্রত্যেকবার নতুন (আগত বা বহির্গামী) সংযোগ তৈরি হওয়ার পরে আমাকে তালিকায় লক করতে হবে, যেহেতু অন্যান্য থ্রেডগুলি এই তালিকায় অ্যাক্সেস করতে পারে, তবে অচলাবস্থার সমস্যাটি এখনও থেকেই যাবে।

আপডেট 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
}

উদাহরণ: আইপি: নোডের পোর্টটি হ'ল এ: 7001 - আইপি: নোড বি এর বন্দরটি বি: 8001।

মনে করুন যে নোড এ নোড বি: 8001 এ একটি লগইন অনুরোধ প্রেরণ করেছে। এই ক্ষেত্রে, নোড এ তার নিজস্ব শ্রবণ ঠিকানা (এ: 7001) প্রেরণ করে লগইন রুটিনকে কল করে। ফলস্বরূপ, নোড এ এর ​​প্রতিবেশী_সারণীতে রিমোট নোডের ঠিকানা রয়েছে (বি: 8001): এই ঠিকানাটি সংযোগের স্থিতির সাথে সম্পর্কিত। নোড এ নোড বি লগইনের অনুরোধ গ্রহণ বা অস্বীকার করার অপেক্ষায় রয়েছে।

এদিকে নোড বি নোড এ (এ: 1০০১) এর ঠিকানায় সংযোগের অনুরোধটি প্রেরণ করতে পারে, নোড এ নোড বিয়ের অনুরোধটি প্রক্রিয়াকরণ করতে পারে, সুতরাং নোড বি এর প্রতিবেশী_সমাথায় রিমোটের ঠিকানা রয়েছে নোড (এ: 7001): এই ঠিকানাটি সংযোগের রাজ্যের সাথে সম্পর্কিত। নোড বি নোডের জন্য অপেক্ষা করছে একটি লগইনের অনুরোধ গ্রহণ বা অস্বীকার করবে।

নোড এ এর ​​সার্ভার সাইডটি যদি বি: 8001 এর অনুরোধটি প্রত্যাখ্যান করে তবে আমার অবশ্যই নিশ্চিত নোড বি এর সার্ভার দিকটি এ: 7001 থেকে অনুরোধটি গ্রহণ করবে। একইভাবে, নোড বি এর সার্ভার সাইডটি যদি এ: 7001 এর অনুরোধটি প্রত্যাখ্যান করে তবে আমার অবশ্যই নিশ্চিত নোড এ এর ​​সার্ভার সাইডটি বি: 8001 থেকে অনুরোধটি গ্রহণ করবে।

মতে "ছোট ঠিকানা" নিয়ম এই ক্ষেত্রে নোড এ, নোড বি দ্বারা লগইন অনুরোধে প্রত্যাখ্যান যখন নোড বি নোড A. থেকে অনুরোধটি স্বীকার করবে

তুমি এটা সম্পর্কে কী ভাব?


এই ধরণের অ্যালগরিদমগুলি বিশ্লেষণ এবং প্রমাণ করা বেশ শক্ত। তবে, এমন একজন গবেষক আছেন যিনি বিতরণকৃত কম্পিউটিংয়ের দুর্দান্ত অনেকগুলি ক্ষেত্রে বিশেষজ্ঞ। : এ লেসলি Lamport এর প্রকাশনা পৃষ্ঠা দেখুন research.microsoft.com/en-us/um/people/lamport/pubs/pubs.html
DeveloperDon

উত্তর:


3

আপনি একটি "আশাবাদী" পদ্ধতির চেষ্টা করতে পারেন: প্রথমে সংযোগ করুন, তারপরে আপনি যদি যুগপত পারস্পরিক সংযোগ সনাক্ত করেন তবে সংযোগ বিচ্ছিন্ন করুন। আপনি নতুন সংযোগ করার সময় এইভাবে সংযোগের অনুরোধগুলি আপনার বাইরে রাখার দরকার নেই: আগত সংযোগটি স্থাপন করার পরে তালিকাটি লক করুন এবং দেখুন একই হোস্টের সাথে আপনার বহির্গামী সংযোগ রয়েছে কিনা। আপনি যদি করেন তবে হোস্টের ঠিকানা চেক করুন। এটি যদি আপনার চেয়ে ছোট হয় তবে আপনার বহির্গামী সংযোগটি সংযোগ বিচ্ছিন্ন করুন; অন্যথায়, আগতটি সংযোগ বিচ্ছিন্ন করুন। আপনার পিয়ার হোস্ট বিপরীতে কাজ করবে, কারণ ঠিকানাগুলি আলাদাভাবে তুলনা করবে এবং দুটি সংযোগের মধ্যে একটি বাদ দেওয়া হবে। এই পদ্ধতির সাহায্যে আপনাকে আপনার সংযোগগুলি আবার চেষ্টা করা এড়াতে দেয় এবং সম্ভাব্যভাবে আপনাকে প্রতি ইউনিট আরও সংযোগের অনুরোধগুলি গ্রহণ করতে সহায়তা করে।


তবে, তবুও আমাকে তালিকায় লক করতে হবে প্রতিবারই নতুন (আগত বা বহির্গামী) সংযোগ তৈরি হওয়ার পরে যেহেতু অন্যান্য থ্রেডগুলি এই তালিকাটিতে অ্যাক্সেস করতে পারে, তখনও অচলাবস্থার সমস্যাটি থেকেই যায়।
enzom83

@ এনজম ৩৩ না, এই স্কিমের অধীনে অচলাবস্থা সম্ভব নয়, কারণ পীরটিকে আপনার লকিংয়ের প্রয়োজন হয় না এমন ক্রিয়াকলাপটি শেষ করার জন্য অপেক্ষা করার দরকার নেই। আপনার তালিকার অভ্যন্তরগুলিকে সুরক্ষিত করার জন্য নিঃশব্দ; একবার আপনি এটি অর্জন করার পরে, আপনি একটি জ্ঞাত পরিমাণে ছেড়ে যান, কারণ আপনাকে সমালোচনামূলক বিভাগে অন্য কোনও সংস্থার জন্য অপেক্ষা করার দরকার নেই।
ডেসব্লিংকনলাইট

ঠিক আছে, তবে সংযোগের অনুরোধটি অবিচ্ছিন্ন না হলে এবং অচলাবস্থার মধ্যে যদি এটি সম্পাদিত হয় তবে অচলাবস্থার সৃষ্টি হতে পারে : এই ক্ষেত্রে নোড তার সংযোগের অনুরোধ গ্রহণ না করা অবধি মিউটেক্স ছাড়তে পারে না। অন্যথায় আমার তালিকায় লকটি কেবল একটি নোড যুক্ত (বা অপসারণ) করার জন্য করা উচিত: এক্ষেত্রে আমার ডুপ্লিকেট সংযোগ ইত্যাদি পরীক্ষা করা উচিত Finally অবশেষে, অন্য একটি বিকল্প হ'ল অ্যাসিনক্রোনাস সংযোগের অনুরোধ প্রেরণ করা।
enzom83

1
@ enzom83 যতক্ষণ না আপনি সমালোচনামূলক বিভাগের মধ্যে থেকে সংযোগের জন্য অনুরোধ করবেন না, আপনি কোনও বিতরণ করা অচলাবস্থা পাবেন না। এটি আশাবাদী পদ্ধতির পিছনে ধারণা - আপনি কেবল একটি নোড যুক্ত করতে বা অপসারণের জন্য তালিকায় একটি লক সঞ্চালন করেন এবং নোড যুক্ত করার সময় যদি আপনি একটি সদৃশ সংযোগ খুঁজে পান তবে "ছোট ঠিকানা" ব্যবহার করে সমালোচনামূলক বিভাগ ছেড়ে যাওয়ার পরে আপনি এটি ভেঙে ফেলেন বিধি (উত্তর থেকে)।
dasblinkenlight

4

যখন একটি নোড অন্যটিতে একটি অনুরোধ প্রেরণ করে, এটিতে এলোমেলো 64৪-বিট পূর্ণসংখ্যার অন্তর্ভুক্ত থাকতে পারে। যখন কোনও নোড সংযোগের অনুরোধ পেয়ে থাকে, যদি এটি ইতিমধ্যে এর নিজস্ব একটি প্রেরণ করে থাকে তবে এটি একটিকে সর্বোচ্চ সংখ্যার সাথে রাখে এবং অন্যগুলিকে ফেলে দেয়। উদাহরণ স্বরূপ:

সময় 1: একটি বি সাথে সংযোগ করার চেষ্টা করে, 123 নম্বর প্রেরণ করে।

সময় 2: বি A এর সাথে সংযোগ স্থাপনের চেষ্টা করে, 234 নম্বর প্রেরণ করে।

সময় 3: বি এ এর ​​অনুরোধ গ্রহণ করে। যেহেতু বি এর নিজস্ব অনুরোধের সংখ্যা বেশি, এটি এ এর ​​অনুরোধ অস্বীকার করে।

সময় 4: এ খ এর অনুরোধ গ্রহণ করে। যেহেতু বি এর অনুরোধের একটি উচ্চতর সংখ্যা রয়েছে, এ এটি গ্রহণ করে এবং নিজস্ব অনুরোধটি বাদ দেয়।

এলোমেলো সংখ্যা তৈরি করতে, নিশ্চিত হয়ে নিন যে আপনি আপনার এলোমেলো নম্বর জেনারেটরের ডিফল্ট সিডিং ব্যবহার না করে, যা প্রায়শই প্রাচীর ঘড়ির সময়ের উপর ভিত্তি করে তৈরি করা হয় তার পরিবর্তে / dev / urandom দিয়ে আপনার এলোমেলো সংখ্যার জেনারেটর বীজ বানাবেন: একটি অজ্ঞাত সুযোগ নেই যে দুটি নোড একই বীজ পাবেন।

এলোমেলো সংখ্যার পরিবর্তে, আপনি সময়ের আগে সংখ্যাগুলি বিতরণও করতে পারেন (যেমন 1 থেকে n পর্যন্ত সমস্ত মেশিনই সংখ্যা), বা একটি ম্যাক ঠিকানা ব্যবহার করতে পারেন, বা কোনও সংখ্যার সন্ধানের অন্য কোনও উপায় যেখানে সংঘর্ষের সম্ভাবনাটি এত কম উপেক্ষণীয়।


3

যদি আমি বুঝতে পারি, আপনি যে সমস্যাটি এড়াতে চাইছেন তা এরকম হয়:

  • নোড 1 নোড 2 থেকে সংযোগের অনুরোধ করে
  • নোড 1 সংযোগ তালিকাকে লক করে
  • নোড 2 নোড 1 থেকে সংযোগের অনুরোধ করে
  • নোড 2 সংযোগের তালিকায় লক করে
  • নোড 2 নোড 1 থেকে সংযোগের অনুরোধ গ্রহণ করে, তালিকাটি লক করা আছে বলে প্রত্যাখ্যান করে
  • নোড 1 নোড 2 থেকে সংযোগের অনুরোধ গ্রহণ করে, তালিকাটি লক করা আছে বলে প্রত্যাখ্যান করে
  • উভয়ই একে অপরের সাথে সংযোগ স্থাপন করে না।

আমি এটি মোকাবেলার জন্য বেশ কয়েকটি ভিন্ন উপায় সম্পর্কে ভাবতে পারি।

  1. যদি আপনি কোনও নোডের সাথে সংযোগ স্থাপনের চেষ্টা করেন এবং এটি "তালিকৃত তালিকায় থাকা" বার্তাটি দিয়ে আপনার অনুরোধটি প্রত্যাখ্যান করে, আবার চেষ্টা করার আগে এলোমেলোভাবে মিলিসেকেন্ডের জন্য অপেক্ষা করুন। (এলোমেলোতা সমালোচনামূলক It এটি এতটা কম সম্ভাবনা তৈরি করে যে উভয়ই ঠিক একই সময়ের জন্য অপেক্ষা করবে এবং একই সমস্যা বিজ্ঞাপনের পুনরাবৃত্তি করবে ))
  2. উভয় সিস্টেমের ঘড়িগুলিকে একটি টাইম সার্ভারের সাথে সিঙ্ক্রোনাইজ করুন এবং সংযোগের অনুরোধের সাথে একটি টাইমস্ট্যাম্প প্রেরণ করুন। আপনি বর্তমানে সংযোগ দেওয়ার চেষ্টা করছেন এমন নোড থেকে যদি কোনও সংযোগের অনুরোধ আসে তবে উভয় নোড সম্মত হন যে যে কোনও একটিই প্রথম জয়কে সংযুক্ত করার চেষ্টা করেছিল এবং অন্য সংযোগটি বন্ধ হয়ে যায়।

সমস্যাটি হ'ল অনুরোধটি প্রাপ্ত নোড সংযোগটি প্রত্যাখ্যান করতে পারে না, তবে তালিকায় লক পাওয়ার জন্য এটি অনির্দিষ্ট সময়ের জন্য অপেক্ষা করবে।
enzom83
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.