Dağıtılmış bir kilitleme deseni mi arıyorsunuz?


10

C # 'da dağıtılmış bir sistem için özel bir özyinelemeli nesne kilitleme mekanizması \ desen bulmak gerekir. Aslında çok düğümlü bir sistemim var. Her düğümün n- sayısı durum parçaları üzerinde özel yazma izinleri vardır . Aynı durum, en az bir başka düğümde salt okunur biçimde de mevcuttur . Bazı yazma / güncellemeler tüm düğümlerde atomik olmalıdır, diğer güncellemeler sonunda arka plan çoğaltma işlemleri, kuyruklar vb.

Atomik güncellemeleri için ben verimli beni için kilitli olarak bir nesneyi işaretlemek için izin bir desen veya numuneler arıyorum yazıyor sistem eşzamanlılık yüksek seviyelerini olduğundan ... vb işlemek, o zaman dağıtabildikleri, geri alma, ben Zaman aşımına uğrayacak veya kilitler serbest bırakıldıktan sonra açılacak kilitleri biriktirebileceğimi varsayıyorum.

İşlem veya mesajlaşma parçaları bu sorunun odağı değil, ancak bazı ekstra içerikler sağladım. Bununla birlikte, isterseniz hangi mesajların gerekli olacağını düşündüğünüzü ifade etmekten çekinmeyin.

İşte tüm yeni ürünleri uygulamak dışında yeni fikirlere açık olmama rağmen öngördüğüm şeyin belirsiz bir örneği

thing.AquireLock(LockLevel.Write);

//Do work

thing.ReleaseLock();

Böyle bir şeye benzeyen uzatma yöntemleri kullanmayı düşünüyordum

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;
}

Birkaç ayrıntıya açıklık getirmek için ...

  • Tüm iletişim ikili istek / yanıt protokolü kullanılarak TCP / IP'dir
  • Kuyruklar veya veritabanları gibi aracı teknolojiler yoktur
  • Merkezi ana düğüm yok. Bu durumda, kilitleme düzenlemesi, kilidin başlatıcısı ve davranışı yönetmek için bir çeşit zaman aşımı ile talebi onurlandıran ortak tarafından tanımlanır.

Herhangi birinin önerisi varmı?


Kilitler genellikle çoğu sistemde standart bir özelliktir. Sanırım C # için de var. (Bir google arama sonucu: albahari.com/threading/part2.aspx ) Temel Muteks veya semaforların ötesinde bir şey elde etmeye mi çalışıyorsunuz?
Dipan Mehta

2
@DipanMehta Üzgünüm, bunu daha açık bir şekilde ele almalıydım. Düğümleri bahsettiğim bir ağda makineleridir. Mutex ve Semaphores anlayışım, makinedeki kilitler ( örn. Çapraz işlem ) ve bir ağdaki makineler arasında uzayabilecek kilitler değil.
JoeGeeky

@JoeGeeky Sorunuz burada konu ile ilgilidir ve Yığın Taşması için muhtemelen çok teorik olacaktır . Orada yeniden sormak isterseniz, daha fazla kod odaklı bir ifade isteyeceksiniz.
Adam Lear

Yanıtlar:


4

Açıklamalar için teşekkürler.

Bu durumda, önerebileceğim bir yayınlama / abone olma modeli kullanmaktır. Google'ın Tombul dağıtılmış kilitleme protokolü ( Paxos uygulaması )

Ben Paxos (veya Chubby'den) kullanılabilir, ancak açık kaynak uygulaması var gibi görünüyor hiç burada .

Bu işe yaramazsa, örneğin mesajlaşma kitaplıkları açısından olağan şüphelilerden birini kullanarak kendi Paxos sürümünüzü uygulayabilirsiniz: sıfır mesaj kuyruğu kitaplığı , RabbitMQ veya ActiveMQ .


Önceki Cevap:

SO ( [A] , [B] ) ile ilgili önerilerin çoğu, makineler arası kilitleme elde etmek için bir mesaj kuyruğunun kullanımına yöneliktir.

Kişisel AcquireLockyöntem başarı önce kilitleri önceki örnekleri için kontrol kuyruğuna kilit nesnesini tanımlayan şey itmek olacaktır. Kişisel ReleaseLockyöntem kuyruğundan kilit nesnesini ortadan kaldıracaktır.

SO kullanıcı atlantis , bu yazıda , bazı ayrıntılar için Jeff Key'in gönderisini önermektedir .


Teşekkürler, ancak merkezi çözüm, veritabanı veya kuyruğum olmadığından bu çözümler uygun olmaz. Bu ayrıntılardan bazılarını netleştirmek için soruyu bazı ek ayrıntılarla güncelledim.
JoeGeeky

Düğümler arasındaki tüm iletişim için kullanmam gereken iyi tanımlanmış bir protokol olduğundan, bu ürünleri doğrudan kullanamayacağım, ancak Chubby ve Paxos, öğrenebileceğim iyi tanımlanmış kalıplara sahip olabilir. Bir bakacağım.
JoeGeeky

@JoeGeeky Evet, Paxos bağlantısında , tercih ettiğiniz iletişim bağlantısını kullanarak uygulamanızı sağlayacak sıra diyagramları vardır.
Peter K.

Doğrudan bir cevap olmasa da, tüm Tombul ve Paxos şeylerini okumak kendi çözümümü tanımlamama yardımcı oldu. Bu araçları kullanmadım, ancak bazı kavramlarına dayanarak makul bir model tanımlayabildim. Teşekkürler.
JoeGeeky

@JoeGeeky: En azından biraz yardımcı olduğunu duymak güzel. Kene için teşekkürler.
Peter K.

4

Bana burada birkaç karma teknolojiniz var gibi görünüyor:

  • iletişim (esasen% 100 güvenilir olarak güvendiğiniz ... ölümcül olabilen)

  • kilitleme / karşılıklı dışlama

  • zaman aşımları (hangi amaçla)?

Uyarı: Dağıtım sistemlerindeki zaman aşımları tehlike ve zorluklarla dolu olabilir. Kullanılırsa, çok dikkatli bir şekilde ayarlanmalı ve kullanılmalıdır, çünkü zaman aşımlarının gelişigüzel kullanımı bir sorunu çözmez, sadece felaketi ortadan kaldırır. (Zaman aşımlarının nasıl kullanılması gerektiğini görmek istiyorsanız , HDLC iletişim protokolü belgelerini okuyun ve anlayın. Bu, IDLE satırı gibi şeylerin algılanmasına izin vermek için akıllı bir bit kodlama sistemi ile birlikte uygun ve akıllı kullanıma iyi bir örnektir. .

Bir süre iletişim bağlantıları (TCP değil, başka bir şey) kullanılarak bağlanmış çok işlemcili dağıtılmış sistemlerde çalıştım. Öğrendiğim şeylerden biri, kaba bir genelleme olarak, gidilecek bazı tehlikeli çoklu programlama yerlerinin olmasıydı:

  • kuyruklara güven genellikle gözyaşlarıyla sona erer (kuyruk doldurulursa, sorun yaşarsınız. SADECE asla doldurmayacak bir kuyruk boyutu hesaplayabilirsiniz, bu durumda muhtemelen kuyruksuz bir çözüm kullanabilirsiniz)

  • Kilitlemeye güvenmek acı vericidir, başka bir yol olup olmadığını deneyin ve düşünün (kilitleme kullanmanız gerekiyorsa, literatüre bakın, çok işlemcili dağıtılmış kilitleme son 2-3 yıldaki birçok asedemik kağıdın konusu olmuştur)

Ben kilitleme kullanarak devam etmek zorunda, o zaman:

Zaman aşımlarını yalnızca son çare kurtarma aracı olarak kullanacağınızı varsayacağım - yani temel iletişim sisteminin arızasını tespit etmek için. Ayrıca TCP / IP iletişim sisteminizin yüksek bant genişliğine sahip olduğunu ve düşük gecikme süresi olarak düşünülebileceğini varsayacağım (ideal olarak sıfır, ancak bu asla gerçekleşmez).

Ne önerebilirim her düğüm bağlanabilir diğer düğümlerin bir bağlantı listesine sahip olmasıdır. (Düğümler bir bağlantının nereden geldiğini umursamazlar.) Bir düğümün bağlanabileceği tabloların popülasyonu, sıralamak için ayrı bir şey olarak bırakılır, bunun statik olarak ayarlanıp ayarlanmayacağını söylemediniz. Ayrıca, bağlantıların bir düğüme geleceği IP bağlantı noktası numaralarının tahsisi gibi şeyler de göz ardı edilir - yalnızca tek bir bağlantı noktasında veya birden fazla bağlantı noktasında istekleri kabul etmek için iyi nedenler olabilir. Bunun dikkatle ele alınması gerekir. Örtük kuyruk, sipariş, kaynak kullanımı, işletim sistemi türü ve yetenekleri içerecektir.

Düğümler kime bağlandıklarını öğrendikten sonra, o düğüme bir kilit isteği gönderebilir ve bu uzak düğümden gelen bir kilit yanıtından geri almaları gerekir. Atomik görünmesi için bu iki işlemi bir sargıya paketleyebilirsiniz. Bunun etkisi, bir kilit almak isteyen düğümlerin aşağıdaki gibi bir arama yapmasıdır:

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 ve release_lock çağrıları aşağıdaki gibi olmalıdır (prensipte):

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

Bir kilit basılıyken gerçekleştirilen iş birimlerinin küçük ve hızlı olması nedeniyle dağıtılmış bir kilitleme sistemi ile çok dikkatli olmanız gerekir çünkü kilit almak için beklemede olan birçok uzak düğümünüz olacaktır. Bu, etkili ancak mümkün olan en yüksek performansa sahip olmayan, dur ve bekle çok işlemcili / iletişim sistemidir.

Bir öneri tamamen farklı bir yaklaşım benimsemektir. Her RPC çağrısının alıcı tarafından işlenebilen ve kilit gereksinimlerini ortadan kaldıran bir bilgi paketi taşıdığı uzak yordam çağrısı kullanabilir misiniz?


Soruyu yeniden okurken, şeylerin iletişim tarafı ile gerçekten ilgilenmek istemiyorsunuz, sadece kilitleme sorununuzu çözmek istiyorsunuz gibi görünüyor.

Bu nedenle cevabım biraz konu dışı görünebilir, ancak altında kalan parçaları da doğru yapmadan kilitleme sorununuzu çözemeyeceğinize inanıyorum. Analoji: Kötü temeller üzerine bir ev inşa etmek onun yıkılmasına neden olur ... Sonunda.


1
Zaman aşımı semantiği büyük ölçüde ağdan kaybolan düğümlerle uğraşmak ya da kilitleme yığınlarındaki büyük birikintilerle uğraşmak için vardır ... Bu, bir kilit elde etmek için beklerken engellenen zamanı sınırlayacak ve kilit isteyen bir fırsat sağlayacaktır. beklenmedik gecikmeler, başarısızlıklar, vb. ortasında diğer süreçleri başlatmak ... Ayrıca, bir şeyin başarısız olması durumunda bir şeyin sonsuza kadar kilitlenmesini önleyecektir. Endişelerinizi takdir ediyorum, ancak bu noktada, sonunda bir şeyin başarısız olacağı göz önüne alındığında alternatif göremiyorum
JoeGeeky

Diğer yorumlarınızdan bazılarıyla konuşmak için, kilitlerin bir FIFO deseni kullanılarak istiflenmesini ve serbest bırakılmasını beklesem de, kendiliğinden (async iletişim anlamında) sıra kullanmıyorum. Bunun bir şekilde engellenmesi ve daha büyük bir el sıkışmasının bir parçası olması gerekenden başka gerekli istek / yanıt deseni açısından nasıl çalışacağını tam olarak uzlaştırmadım. Şu anda, tek bir düğüm içinde yığılmış kilitleme mekanizması ve daha sonra dağıtılmış senaryo ile nasıl çalışacağım. Önerdiğin gibi biraz daha okuma yapacağım. Teşekkürler
JoeGeeky

@JoeGeeky - bir FIFO bir kuyruktur. Kuyruklara dikkat edin. O tarafı çok dikkatli düşünün. Sadece "raftan" bir şey almayacaksınız gibi görünüyor ama probleminizi ve çözümünüzü dikkatlice düşünmek zorunda kalacaksınız.
quickly_now

Anlıyorum ... Zaman uyumsuz işlemlerde kullanılan bir FIFO kuyruğundaki farkı açıklığa kavuşturmaya çalışıyordum ( örneğin, bir süreç enqueues ve sonra başka dequeues ). Bu durumda, şeylerin sırayla yönetilmesi gerekir, ancak kuyruğa giren işlem (a) kilidi alana kadar, (b) bir kilit reddedilene veya (c) zaman aşımına uğramadan ve hattan ayrılana kadar ayrılmaz. Daha çok ATM'de sıraya girmek gibi. Bu, başarı durumunda bir FIFO modeli gibi davranır, ancak çizginin önüne ulaşmadan önce işlemler düzensiz kalabilir. Hazır mı? Hayır, ama bu yeni bir sorun değil
JoeGeeky

0

Sorunuz NCache gibi dağıtılmış bir önbellek kullanılarak kolayca uygulanabilir. İhtiyacınız olan şey, bir nesne kullanarak bir kilit elde edebileceğiniz kötümser bir kilitleme mekanizmasıdır. Ardından görevlerinizi ve işlemlerinizi gerçekleştirin ve daha sonra diğer uygulamaların kullanması için kilidi serbest bırakın.

Aşağıdaki koda bir göz atın;

Burada belirli bir Anahtar üzerinde bir kilit elde edersiniz ve daha sonra görevleri gerçekleştirirsiniz (bir veya daha fazla işlemden itibaren) ve ardından işiniz bittiğinde kilidi serbest bırakırsınız.

// 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
}

Bağlantıdan alınmıştır: http://blogs.alachisoft.com/ncache/distributed-locking/

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.