एक वितरित लॉकिंग पैटर्न की तलाश में


10

मुझे C # में वितरित सिस्टम के लिए कस्टम पुनरावर्ती ऑब्जेक्ट लॉकिंग मैकेनिज्म \ पैटर्न के साथ आने की आवश्यकता है। अनिवार्य रूप से, मेरे पास एक बहु-नोड प्रणाली है। प्रत्येक नोड में राज्य के n -number टुकड़ों पर अनन्य लेखन अनुमति है । वही राज्य कम से कम एक अन्य नोड पर केवल-पढ़ने के लिए भी उपलब्ध है । कुछ लिखते हैं / अपडेट सभी नोड्स में परमाणु होना चाहिए, जबकि अन्य अपडेट अंततः लगातार पृष्ठभूमि की प्रतिकृति प्रक्रियाओं, कतारों, आदि के माध्यम से बनेंगे ...

परमाणु अद्यतनों के लिए, मैं एक ऐसे पैटर्न या नमूने की तलाश कर रहा हूं, जो कुशलतापूर्वक मुझे एक ऑब्जेक्ट को लिखने के लिए लॉक के रूप में चिह्नित करने की अनुमति देता है, जिसे मैं फिर वितरित कर सकता हूं, प्रतिबद्ध कर सकता हूं, रोलबैक कर सकता हूं ... क्योंकि सिस्टम में उच्च-स्तर की संगामिति है, मैं मुझे लगता है कि मैं ताले को स्टैक-अप करने में सक्षम होने की आवश्यकता होगी, जो लॉक होने के बाद या तो टाइमआउट हो जाएगा या अनियंत्रित हो जाएगा।

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

यहाँ एक अस्पष्ट नमूना है कि मैं क्या कल्पना कर रहा था, हालांकि मैं नए उत्पादों को लागू करने से अलग किसी भी नए विचारों के लिए खुला हूं

thing.AquireLock(LockLevel.Write);

//Do work

thing.ReleaseLock();

मैं विस्तार के तरीकों का उपयोग करने के बारे में सोच रहा था, जो कुछ इस तरह दिख सकता है

public static void AquireLock(this IThing instance, TupleLockLevel lockLevel)
{ 
    //TODO: Add aquisition wait, retry, recursion count, timeout support, etc...  
    //TODO: Disallow read lock requests if the 'thing' is already write locked
    //TODO: Throw exception when aquisition fails
    instance.Lock = lockLevel;
}

public static void ReleaseLock(this IThing instance)
{
    instance.Lock = TupleLockLevel.None;
}

कुछ विवरण स्पष्ट करने के लिए ...

  • सभी संचार बाइनरी अनुरोध / प्रतिक्रिया प्रोटोकॉल का उपयोग करते हुए टीसीपी / आईपी हैं
  • कोई भी मध्यस्थ तकनीकें जैसे कतार या डेटाबेस नहीं हैं
  • कोई केंद्रीय मास्टर नोड नहीं है। इस मामले में, लॉकिंग व्यवस्था को लॉक के सर्जक द्वारा परिभाषित किया गया है और साथी जो अपने व्यवहार को संचालित करने के लिए कुछ समय के लिए अनुरोध का सम्मान करेगा

किसी के पास कोई सुझाव है?


अधिकांश प्रणालियों में आमतौर पर ताले एक मानक विशेषता है। मुझे लगता है कि यह सी # के लिए भी है। (एक Google खोज परिणाम: albahari.com/threading/part2.aspx ) क्या आप मूल म्यूटेक्स या एनाफ़ोर्स से परे कुछ हासिल करने की कोशिश कर रहे हैं?
दीपन मेहता

2
@DipanMehta क्षमा करें, मुझे इसे अधिक स्पष्ट रूप से संबोधित करना चाहिए। मैंने जिन नोड्स का उल्लेख किया है वे एक नेटवर्क पर मशीनें हैं। म्यूटेक्स और सेमाफोरस के बारे में मेरी समझ यह है कि वे मशीन-वाइड लॉक ( जैसे क्रॉस-प्रोसेस ) हैं न कि वे लॉक जो किसी नेटवर्क पर मशीनों के बीच विस्तार कर सकते हैं।
जोजी डिक

@JoeGeeky आपका प्रश्न यहां विषय पर है और संभवतः स्टैक ओवरफ्लो के लिए भी सैद्धांतिक होगा । यदि आप इसे फिर से पूछना चाहते हैं तो आप कर सकते हैं, लेकिन आप एक और अधिक कोड-केंद्रित फ़ुटासिंग चाहते हैं।
एडम लेअर

जवाबों:


4

स्पष्टीकरण के लिए धन्यवाद।

उस मामले में, जो मैं सुझाऊँगा वह एक प्रकाशित / सदस्यता मॉडल का उपयोग कर रहा है। Google के चब्बी ने लॉकिंग प्रोटोकॉल ( पैक्सो का कार्यान्वयन ) वितरित किया

मैंने कभी भी पैक्सो (या चब्बी) का उपयोग नहीं किया है, लेकिन यहां एक खुला स्रोत कार्यान्वयन प्रतीत होता है

यदि वह काम नहीं करता है, तो आप अपने स्वयं के संस्करण को लागू कर सकते हैं Paxos का उपयोग कर, उदाहरण के लिए, संदेश पुस्तकालयों के संदर्भ में सामान्य संदिग्धों में से एक: शून्य संदेश कतार पुस्तकालय , RabbitMQ , या ActiveMQ


पिछला उत्तर:

SO ( [A] , [B] पर अधिकांश सुझाव क्रॉस-मशीन लॉकिंग को प्राप्त करने के लिए एक संदेश कतार के उपयोग के लिए जाते हैं।

आपका AcquireLockतरीका कुछ को लॉक ऑब्जेक्ट को कतार में पहचानने से पहले धक्का देगा, सफलता से पहले ताले के पिछले उदाहरणों की जांच करना। आपका ReleaseLockतरीका कतार से लॉक ऑब्जेक्ट को हटा देगा।

एसओ उपयोगकर्ता एटलांटिस सुझाव देते हैं, इस पोस्ट में जेफ की के कुछ विस्तार के लिए पोस्ट


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

मैं इन उत्पादों का सीधे उपयोग नहीं कर पाऊंगा क्योंकि पहले से ही एक अच्छी तरह से परिभाषित प्रोटोकॉल है जिसे मुझे नोड्स के बीच सभी संचारों के लिए उपयोग करना होगा, लेकिन चब्बी और पैक्सोस में अच्छी तरह से परिभाषित पैटर्न हो सकते हैं, जिनसे मैं सीख सकता हूं। मैं एक नजर मार लूगां।
जोजेकी

@JoeGeeky हां, पैक्सोस लिंक में अनुक्रम आरेख हैं जो आपको अपने पसंदीदा संचार लिंक का उपयोग करके इसे लागू करने की अनुमति दे सकते हैं।
पीटर के।

हालांकि इसका सीधा जवाब नहीं है, लेकिन सभी चॉबी और पैक्सोस सामग्री के माध्यम से पढ़ने से मुझे अपने समाधान को परिभाषित करने में मदद मिली। मैंने उन उपकरणों का उपयोग नहीं किया, लेकिन उनकी कुछ अवधारणाओं के आधार पर एक उचित पैटर्न को परिभाषित करने में सक्षम था। धन्यवाद।
जोजेकी

@ जोजीकी: यह सुनने में अच्छा था कि कुछ मदद मिली, कम से कम। टिक के लिए धन्यवाद।
पीटर के।

4

मुझे लगता है कि तुम यहाँ मिश्रित प्रौद्योगिकियों के एक जोड़े है:

  • संचार (जो आप अनिवार्य रूप से 100% विश्वसनीय होने पर निर्भर करते हैं ... जो घातक हो सकता है)

  • लॉकिंग / आपसी बहिष्कार

  • टाइमआउट (किस उद्देश्य के लिए)?

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

एक समय के लिए मैंने मल्टी-प्रोसेसर वितरित सिस्टम में संचार लिंक (टीसीपी नहीं कुछ और) का उपयोग करके काम किया। जिन चीजों को मैंने सीखा, उनमें से एक यह थी कि एक सामान्य सामान्यीकरण के रूप में, कुछ खतरनाक मल्टी प्रोग्रामिंग जगहों पर जाना है:

  • कतारों पर निर्भरता आम तौर पर आँसू में समाप्त हो जाती है (यदि कतार भर जाती है, तो आप मुसीबत में हैं। कम से कम आप एक कतार आकार की गणना कर सकते हैं जो कभी नहीं भरेंगे, इस स्थिति में आप शायद बिना कतार समाधान का उपयोग कर सकते हैं)

  • लॉकिंग पर निर्भरता दर्दनाक है, कोशिश करें और सोचें कि क्या कोई दूसरा तरीका है (यदि आपको लॉकिंग का उपयोग करना चाहिए, तो साहित्य को देखें, मल्टी-प्रोसेसर वितरित लॉकिंग पिछले 2-3 दशकों के कई एसेडेमिक पेपर का विषय रहा है)

मुझे आपको लॉकिंग का उपयोग करके आगे बढ़ना होगा, फिर:

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

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

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

if (get_lock(remote_node) == timeout) then
  {
    take some failure action - the comms network is down
  }

/* Lock is now acquired - do work here */

if (release_lock(remote_node) == timeout) then
  {
    take some failure action - the comms network is down
  }

कॉल get_lock और release_lock कुछ इस तरह से होने चाहिए (सिद्धांत रूप में):

send_to_remote_node(lock_request)
get_from_remote_node_or_timeout(lock_reply, time)
if (result was timeout) then
  return timeout
else
  return ok

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

एक सुझाव पूरी तरह से अलग दृष्टिकोण लेने के लिए है। क्या आप एक दूरस्थ प्रक्रिया कॉल का उपयोग कर सकते हैं, जहां प्रत्येक RPC कॉल जानकारी का एक पैकेज लेती है जिसे प्राप्तकर्ता द्वारा नियंत्रित किया जा सकता है, और जो ताले की जरूरतों को दूर करता है?


प्रश्न को फिर से पढ़ने पर, ऐसा लगता है कि आप वास्तव में चीजों के संचार पक्ष से चिंतित नहीं होना चाहते हैं, आप सिर्फ अपने लॉकिंग मुद्दे को हल करना चाहते हैं।

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


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

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

@ जेजेकी - एक फीफो एक कतार है। कतारों से सावधान रहें। उस पक्ष को बहुत ध्यान से सोचें। ऐसा लगता है कि आप केवल "शेल्फ से कुछ" प्राप्त करने के लिए नहीं जा रहे हैं, लेकिन आपको अपनी समस्या और समाधान के बारे में सावधानी से सोचना होगा।
जल्‍दी से जल्‍दी से जल्‍दी

मैं समझता हूँ ... मैं async प्रक्रियाओं में प्रयुक्त एक FIFO कतार ( जैसे एक प्रक्रिया enqueues और फिर एक और dequeues ) के अंतर को स्पष्ट करने की कोशिश कर रहा था । इस मामले में, चीजों को क्रम में प्रबंधित करने की आवश्यकता होगी, लेकिन कतार में प्रवेश करने की प्रक्रिया तब तक नहीं छोड़ेगी जब तक (ए) उन्हें ताला नहीं मिलता है, (बी) एक लॉक से इनकार कर दिया जाता है, या (ग) वे समय समाप्त कर देते हैं और लाइन छोड़ देते हैं। एटीएम में लाइन में खड़ा होना ज्यादा पसंद है। यह सफलता के मामले में एक फीफो पैटर्न की तरह व्यवहार करता है, लेकिन प्रक्रिया लाइन के सामने पहुंचने से पहले क्रम से बाहर निकल सकती है। ऑफ-द-शेल्फ के लिए? नहीं, लेकिन यह कोई नई समस्या नहीं है
जोजी डिक

0

आपके प्रश्न को NCache जैसे वितरित कैश का उपयोग करके आसानी से लागू किया जा सकता है। आपको जिस चीज की आवश्यकता है वह एक निराशावादी लॉकिंग तंत्र है जहां आप किसी ऑब्जेक्ट का उपयोग करके लॉक को प्राप्त कर सकते हैं। फिर अपने कार्यों और कार्यों का प्रदर्शन करें और बाद में उपभोग करने के लिए अन्य अनुप्रयोगों के लिए लॉक जारी करें।

निम्नलिखित कोड पर एक नज़र डालें;

यहां आप एक विशिष्ट कुंजी पर लॉक प्राप्त करेंगे और फिर कार्य करेंगे (एक या एक से अधिक ऑपरेशनों से) फिर अंत में ताला जारी करें जब आप काम कर रहे हों।

// Instance of the object used to lock and unlock cache items in NCache
LockHandle lockHandle = new LockHandle();

// Specify time span of 10 sec for which the item remains locked
// NCache will auto release the lock after 10 seconds.
TimeSpan lockSpan = new TimeSpan(0, 0, 10); 

try
{
    // If item fetch is successful, lockHandle object will be populated
    // The lockHandle object will be used to unlock the cache item
    // acquireLock should be true if you want to acquire to the lock.
    // If item does not exists, account will be null
    BankAccount account = cache.Get(key, lockSpan, 
    ref lockHandle, acquireLock) as BankAccount;
    // Lock acquired otherwise it will throw LockingException exception

    if(account != null && account.IsActive)
    {
        // Withdraw money or Deposit
        account.Balance += withdrawAmount;
        // account.Balance -= depositAmount;

        // Insert the data in the cache and release the lock simultaneously 
        // LockHandle initially used to lock the item must be provided
        // releaseLock should be true to release the lock, otherwise false
        cache.Insert("Key", account, lockHandle, releaseLock); 
        //For your case you should use cache.Unlock("Key", lockHandle);
    }
    else
    {
        // Either does not exist or unable to cast
        // Explicitly release the lock in case of errors
        cache.Unlock("Key", lockHandle);
    } 
}
catch(LockingException lockException)
{
    // Lock couldn't be acquired
    // Wait and try again
}

लिंक से लिया गया: http://blogs.alachisoft.com/ncache/distributed-locking/

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.