首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【愚公系列】2023年09月 .NET CORE工具案例-DistributedLock的分布式锁

【愚公系列】2023年09月 .NET CORE工具案例-DistributedLock的分布式锁

作者头像
愚公搬代码
发布2025-06-01 12:30:39
发布2025-06-01 12:30:39
10100
代码可运行
举报
文章被收录于专栏:历史专栏历史专栏
运行总次数:0
代码可运行

前言

锁是一种同步机制,用于在多线程或多进程环境中对共享资源进行互斥访问,从而避免竞争条件和数据不一致问题。

分布式锁是一种在分布式系统中实现互斥访问的锁,允许多个进程或节点使用同一个锁来协调它们的操作。分布式锁通常使用分布式协议来确保锁的一致性和可靠性,例如 ZooKeeper、Redis 等。分布式锁的应用场景包括高并发下的数据更新、分布式任务调度、分布式事务等。

一、DistributedLock的分布式锁

1.概念

DistributedLock(分布式锁)是一种在分布式系统中实现同步或协作的机制。在分布式系统中,多个进程、线程或服务可能同时访问共享资源或执行相同的任务。如果不加控制地访问共享资源,会导致数据不一致或执行结果不可预测的问题。分布式锁通过协调不同节点之间的操作,保证共享资源的安全和正确性。

分布式锁的实现方式有多种,其中比较常见的是基于互斥算法(如基于Zookeeper的实现)、基于缓存(如Redis的实现)等。通过这些机制,分布式锁可以实现锁定和解锁的操作,并确保同一时刻只有一个进程、线程或服务可以访问共享资源。

DistributedLock源码网址:https://github.com/madelson/DistributedLock

2.基本使用

DistributedLock是一个分布式锁的开源库,它提供了多种分布式锁实现方式,可以使用不同的数据存储技术来支持分布式锁。它支持多个分布式锁实例共存,可以适用于多种场景。

使用:

2.1 DistributedLock.SqlServer

使用SqlServer作为数据存储技术,需要先安装SqlServer数据库,并创建名为"Locks"的数据库。然后使用以下代码进行分布式锁的操作:

代码语言:javascript
代码运行次数:0
运行
复制
var connectionString = "your connection string";
var lockName = "your lock name";
using(var sqlLock = new SqlDistributedLock(lockName, connectionString))
{
    try
    {
        sqlLock.TryAcquire(TimeSpan.FromSeconds(30));
        // do something that needs synchronization
    }
    finally
    {
        sqlLock.Release();
    }
}
2.2 DistributedLock.Postgres

使用Postgres作为数据存储技术,需要先安装Postgres数据库,并创建名为"distributed_locks"的数据库。然后使用以下代码进行分布式锁的操作:

代码语言:javascript
代码运行次数:0
运行
复制
var connectionString = "your connection string";
var lockName = "your lock name";
using(var postgresLock = new PostgresDistributedLock(lockName, connectionString))
{
    try
    {
        postgresLock.TryAcquire(TimeSpan.FromSeconds(30));
        // do something that needs synchronization
    }
    finally
    {
        postgresLock.Release();
    }
}
2.3 DistributedLock.MySql

使用MySql作为数据存储技术,需要先安装MySql数据库,并创建名为"Locks"的数据库。然后使用以下代码进行分布式锁的操作:

代码语言:javascript
代码运行次数:0
运行
复制
var connectionString = "your connection string";
var lockName = "your lock name";
using(var mysqlLock = new MySqlDistributedLock(lockName, connectionString))
{
    try
    {
        mysqlLock.TryAcquire(TimeSpan.FromSeconds(30));
        // do something that needs synchronization
    }
    finally
    {
        mysqlLock.Release();
    }
}
2.4 DistributedLock.Oracle

使用Oracle作为数据存储技术,需要先安装Oracle数据库,并创建名为"Locks"的数据库。然后使用以下代码进行分布式锁的操作:

代码语言:javascript
代码运行次数:0
运行
复制
var connectionString = "your connection string";
var lockName = "your lock name";
using(var oracleLock = new OracleDistributedLock(lockName, connectionString))
{
    try
    {
        oracleLock.TryAcquire(TimeSpan.FromSeconds(30));
        // do something that needs synchronization
    }
    finally
    {
        oracleLock.Release();
    }
}
2.5 DistributedLock.Redis

使用Redis作为数据存储技术,需要先安装Redis数据库。然后使用以下代码进行分布式锁的操作:

代码语言:javascript
代码运行次数:0
运行
复制
var connectionString = await ConnectionMultiplexer.ConnectAsync(connectionString); 
//  StackExchange.Redis

var lockName = "your lock name";
using(var redisLock = new RedisDistributedLock(lockName, connectionString))
{
    try
    {
        redisLock.TryAcquire(TimeSpan.FromSeconds(30));
        // do something that needs synchronization
    }
    finally
    {
        redisLock.Release();
    }
}
2.6 DistributedLock.Azure

使用Azure作为数据存储技术,需要先创建Azure Storage。然后使用以下代码进行分布式锁的操作:

代码语言:javascript
代码运行次数:0
运行
复制
var connectionString = "your connection string";
var lockName = "your lock name";
using(var azureLock = new AzureDistributedLock(lockName, connectionString))
{
    try
    {
        azureLock.TryAcquire(TimeSpan.FromSeconds(30));
        // do something that needs synchronization
    }
    finally
    {
        azureLock.Release();
    }
}
2.7 DistributedLock.ZooKeeper

使用ZooKeeper作为数据存储技术,需要先安装ZooKeeper。然后使用以下代码进行分布式锁的操作:

代码语言:javascript
代码运行次数:0
运行
复制
var connectionString = "your connection string";
var lockName = "your lock name";
using(var zooKeeperLock = new ZooKeeperDistributedLock(lockName, connectionString))
{
    try
    {
        zooKeeperLock.TryAcquire(TimeSpan.FromSeconds(30));
        // do something that needs synchronization
    }
    finally
    {
        zooKeeperLock.Release();
    }
}
2.8 DistributedLock.FileSystem

使用文件系统作为数据存储技术,需要指定文件夹作为锁的存储目录。然后使用以下代码进行分布式锁的操作:

代码语言:javascript
代码运行次数:0
运行
复制
var directoryPath = "your directory path";
var lockName = "your lock name";
using(var fileLock = new FileSystemDistributedLock(lockName, directoryPath))
{
    try
    {
        fileLock.TryAcquire(TimeSpan.FromSeconds(30));
        // do something that needs synchronization
    }
    finally
    {
        fileLock.Release();
    }
}
2.9 DistributedLock.WaitHandles

使用WaitHandles作为数据存储技术,需要指定名为"Global\" + lockName的WaitHandle。然后使用以下代码进行分布式锁的操作:

代码语言:javascript
代码运行次数:0
运行
复制
var lockName = "your lock name";
using(var waitHandleLock = new WaitHandleDistributedLock(lockName))
{
    try
    {
        waitHandleLock.TryAcquire(TimeSpan.FromSeconds(30));
        // do something that needs synchronization
    }
    finally
    {
        waitHandleLock.Release();
    }
}

3.读写锁

读写锁是一种多线程并发控制机制,在读多写少的情况下可以提高并发访问效率。读操作和写操作之间是互斥的,即一个线程在写时其他线程不能读写,但是多个线程可以同时读取数据。读写锁分为读锁和写锁,读锁和写锁可以互斥地占用对共享资源的访问权。如果一个线程占用了写锁,则其他线程无论是读还是写都无法访问,直到写锁被释放。如果一个线程占用了读锁,则其他线程可以继续占用读锁,但写锁将被阻塞,直到所有的读锁都被释放。读写锁能够提高效率的原因就在于,当有多个线程同时需要读取数据时,读锁可以被多个线程同时占用,而写锁只能有一个线程占用,从而避免了读写冲突带来的性能瓶颈。

代码语言:javascript
代码运行次数:0
运行
复制
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) { /* 写入数据 */ }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、DistributedLock的分布式锁
    • 1.概念
    • 2.基本使用
      • 2.1 DistributedLock.SqlServer
      • 2.2 DistributedLock.Postgres
      • 2.3 DistributedLock.MySql
      • 2.4 DistributedLock.Oracle
      • 2.5 DistributedLock.Redis
      • 2.6 DistributedLock.Azure
      • 2.7 DistributedLock.ZooKeeper
      • 2.8 DistributedLock.FileSystem
      • 2.9 DistributedLock.WaitHandles
    • 3.读写锁
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档