我正在寻找适用于多台机器的锁定机制的建议。在我的情况下,我基本上只是希望能够在 2 台机器上启动一项服务并拥有一个块,直到另一台完成,这是一种确保冗余的简单方法,以防服务机器出现故障。
与分布式锁服务类似,但专门寻找人们已成功与 .NET 集成的项目。
我正在寻找适用于多台机器的锁定机制的建议。在我的情况下,我基本上只是希望能够在 2 台机器上启动一项服务并拥有一个块,直到另一台完成,这是一种确保冗余的简单方法,以防服务机器出现故障。
与分布式锁服务类似,但专门寻找人们已成功与 .NET 集成的项目。
我们使用 SqlServer 的应用程序锁定功能进行分布式锁定。如果 SqlServer 已经是您堆栈的一部分,这将特别方便。
为了让 .NET 更容易使用它,我创建了一个NuGet 包,可以轻松使用此功能。该库还支持其他后端,例如 Postgres、Azure Blob 存储和 Redis。
使用此库,代码如下所示:
var @lock = new SqlDistributedLock("my_lock_name", connectionString);
using (@lock.Acquire())
{
// critical region
}
因为底层的 SqlServer 功能非常灵活,所以也有支持 TryAcquire 语义、超时和异步锁定的重载。
如果您使用的是适用于 Windows Server 的 AppFabric,则可以使用此 DataCache 扩展。您还可以将 redis 锁与ServiceStack 的 redis 客户端一起使用。
两者都是 .NET 实现,但需要一个服务器组件。我一直在修改分布式锁的 PeerChannel 实现,它使用对等通信并且不需要任何服务器基础设施。如果您对此感兴趣,请告诉我。
对于这个使用 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
}