• DistributedLock 一款非常棒的.NET分布式锁库
  • 发布于 2个月前
  • 199 热度
    0 评论
分布式锁
DistributedLock 是一个 .NET 库,它基于各种底层技术,提供了健壮并且易于使用的分布式互斥锁、读写锁和信号量。DistributedLock包含基于各种技术的实现,包括 SqlServer, Redis, Postgres, MySql 等,您可以根据自己的场景不同的实现库。
• DistributedLock.SqlServer
• DistributedLock.Postgres
• DistributedLock.MySql
• DistributedLock.Oracle
• DistributedLock.Redis
• DistributedLock.Azure
• DistributedLock.ZooKeeper
• DistributedLock.FileSystem
• DistributedLock.WaitHandles

如何使用
在分布式场景中,使用 DistributedLock,跨多个应用程序/机器,控制对某个代码块的访问非常简单,如下
await using (await myDistributedLock.AcquireAsync())
{
    // 获取锁, 执行代码
}
DistributedLock.SqlServer 示例
var @lock = new SqlDistributedLock("MyLockName", connectionString);
await using (await @lock.AcquireAsync())
{
   // 获取锁, 执行代码
}
DistributedLock.Redis 示例
var connection = await ConnectionMultiplexer.ConnectAsync(connectionString); 
//  StackExchange.Redis
//  堆代码 duidaima.com
var @lock = new RedisDistributedLock("MyLockName", connection.GetDatabase());
await using (var handle = await @lock.TryAcquireAsync())
{
    if (handle != null) 
    { 
        // 获取锁, 执行代码
    }
}
Reader-writer locks 读写锁
DistributedLock 的读写锁实现和 .NET 中的 ReaderWriterLockSlim 类相似。读写锁允许多个读取者或一个写入者在任何给定时间持有该锁。对于在可以安全进行并发访问,但有的时候又需要锁定的资源,是非常有用的,读写锁可用于在分布式缓存中提供线程安全性。
class DistributedCache
{
    // 使用 Sql Server 实现
    private readonly SqlDistributedReaderWriterLock _cacheLock = 
        new SqlDistributedReaderWriterLock("DistributedCache", connectionString);
        
    // 如果缓存中存在 key, 则返回,否则,生成新的 key,写入后并返回
    public async Task<object> GetOrCreateAsync(string key, Func<string, object> valueFactory)
    {
        // 首先,用 Read 锁尝试获取缓存数据
        await using (await this._cacheLock.AcquireReadLockAsync())
        {
            var cached = await this.GetValueOrDefaultNoLockAsync(key);
            if (cached != null) { return cached; }  
        }
        
        // 缓存不存在,用 Write 锁, 写入数据并返回
        await using (await this._cacheLock.AcquireWriteLockAsync())
        {
            // double-check: 检查是否已经被其他的进程写入数据
            var cached = await this.GetValueOrDefaultNoLockAsync(key);
            if (cached != null) { return cached; }  
            
            // 写入数据并返回
            var generated = valueFactory(key);
            await this.SetValueAsync(key, generated);
            return generated;
        }
    }
    
    private async Task<object?> GetValueOrDefaultNoLockAsync(string key) { /* 读取数据 */ }
    
    private async Task SetValueAsync(string key, object value) { /* 写入数据 */ }
}

用户评论