6

我正在寻找适用于多台机器的锁定机制的建议。在我的情况下,我基本上只是希望能够在 2 台机器上启动一项服务并拥有一个块,直到另一台完成,这是一种确保冗余的简单方法,以防服务机器出现故障。

分布式锁服务类似,但专门寻找人们已成功与 .NET 集成的项目。

4

3 回答 3

13

我们使用 SqlServer 的应用程序锁定功能进行分布式锁定。如果 SqlServer 已经是您堆栈的一部分,这将特别方便。

为了让 .NET 更容易使用它,我创建了一个NuGet 包,可以轻松使用此功能。该库还支持其他后端,例如 Postgres、Azure Blob 存储和 Redis。

使用此库,代码如下所示:

var @lock = new SqlDistributedLock("my_lock_name", connectionString);
using (@lock.Acquire())
{
   // critical region
}

因为底层的 SqlServer 功能非常灵活,所以也有支持 TryAcquire 语义、超时和异步锁定的重载。

于 2016-03-15T11:34:18.273 回答
3

如果您使用的是适用于 Windows Server 的 AppFabric,则可以使用此 DataCache 扩展。您还可以将 redis 锁与ServiceStack 的 redis 客户端一起使用。

两者都是 .NET 实现,但需要一个服务器组件。我一直在修改分布式锁的 PeerChannel 实现,它使用对等通信并且不需要任何服务器基础设施。如果您对此感兴趣,请告诉我。

于 2013-07-30T21:18:40.907 回答
0

对于这个使用 NCache 的特定用例,您可以使用悲观锁定。当您处理读取密集型应用程序时,乐观锁定非常有用

NCache 帮助您实现它。 http://blogs.alachisoft.com/ncache/distributed-locking/

// 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); 
    }
    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
}
于 2016-05-03T06:04:28.793 回答