商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > DistributedLock 实现.Net分布式锁功能

DistributedLock 实现.Net分布式锁功能

  发布于2026-07-23 阅读(0)

扫一扫,手机访问

分布式系统里,最头疼的问题之一就是“抢资源”。举个简单的例子:多个服务节点同时往数据库同一行写数据,或者定时任务在多台机器上同时被触发,再或者多个实例同时更新缓存导致互相覆盖——这些场景下,并发冲突和数据一致性就成了绕不开的坎。要解决这类问题,最直接的手段就是分布式锁

今天想聊的是一个在 .NET 生态里非常趁手的分布式锁库——DistributedLock。它设计得足够轻量,线程安全,且支持多种后端存储,几乎涵盖了主流中间件:Redis、SQL Server、PostgreSQL、MySQL、MongoDB,甚至还包括本地内存模式。切换后端只需要换一个提供程序,代码基本不用动,这才是真正意义上的“一次编写,到处运行”。

什么是 DistributedLock

简单说,它是一个专门用来在分布式环境下实现锁机制的库。支持的后端列表在前面已经提到了,关键是它的 API 设计非常简洁,获取锁、释放锁的逻辑都能用 using 块优雅地完成,不必手动处理超时和异常。

基本使用

安装 NuGet 包

在项目中引入对应的后端包即可。最经典的组合就是 Redis 和 SQL Server:

dotnet add package DistributedLock  
dotnet add package DistributedLock.Redis
dotnet add package DistributedLock.SqlServer

当然,如果你只用其中一种,单独装对应的包就够了。

使用 Redis 分布式锁

var RedisConnectionString = "localhost:6379,abortConnect=false";
var LockName = "MyResourceLock";
var connection = await ConnectionMultiplexer.ConnectAsync(RedisConnectionString); // uses StackExchange.Redis
var @lock = new RedisDistributedLock(LockName, connection.GetDatabase());

await using (var handle = await @lock.TryAcquireAsync())
{
    if (handle != null) { /* I ha ve the lock */ }
}

核心就两步:创建锁对象,然后调用 TryAcquireAsync。拿到 handle 代表获锁成功,代码块执行完自动释放,不需要手动清理资源。

使用 SQL Server 分布式锁

using Medallion.Threading.SqlServer;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace DistributedLockDemo
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            var connectionString = "Server=myServerAddress;Database=Locks;User Id=myUsername;Password=myPassword;";
            var lockName = "MyResourceLock";

            // 创建分布式锁对象(不需要 using,因为它不实现 IDisposable)
            var sqlLock = new SqlDistributedLock(lockName, connectionString);

            // 尝试获取锁,返回的锁句柄(LockHandle)实现了 IDisposable
            using (var lockHandle = sqlLock.TryAcquire(TimeSpan.FromSeconds(30)))
            {
                if (lockHandle != null) // 判断是否成功获取锁
                {
                    // 持有锁,执行需要同步的代码
                    Console.WriteLine("Lock acquired, performing operation...");
                    // 模拟业务操作
                    await Task.Delay(1000); // 建议使用异步延迟而非 Thread.Sleep
                }
                else
                {
                    Console.WriteLine("Failed to acquire lock within the timeout.");
                }
            } // 此处会自动释放锁(lockHandle.Dispose())
        }
    }
}

在定时任务(Quartz、Hangfire 等)场景下,用 SQL Server 锁可以有效防止多节点重复执行——抢到锁的节点干活,其他节点乖乖等待或跳过。

依赖注入集成

在实际项目中,通常会通过依赖注入统一管理锁提供程序。先配好连接字符串:

{
  "ConnectionStrings": {
    "SqlServer": "Server=myServerAddress;Database=Locks;User Id=myUsername;Password=myPassword;",
    "Redis": "localhost:6379"
  }
}

然后在 DI 容器里注册 IDistributedLockProvider

// Startup.cs 或 Program.cs
public void ConfigureServices(IServiceCollection services)
{
    var connectionString = Configuration.GetConnectionString("SqlServer");
    services.AddSingleton(_ => 
        new SqlDistributedSynchronizationProvider(connectionString));
    services.AddTransient();
}

// SomeService.cs
public class SomeService
{
    private readonly IDistributedLockProvider _lockProvider;
    public SomeService(IDistributedLockProvider lockProvider)
    {
        _lockProvider = lockProvider;
    }

    public async Task InitializeUserAccountAsync(int id)
    {
        var @lock = _lockProvider.CreateLock($"UserAccount{id}");
        await using (await @lock.AcquireAsync())
        {
            // 执行需要同步的操作
            Console.WriteLine($"Initializing user account {id}...");
            await Task.Delay(1000);
        }
    }
}

这样一来,所有需要锁的地方只要注入 IDistributedLockProvider 就行,业务代码完全不用关心后端是 Redis 还是 SQL Server。

续租机制与 RedLock

DistributedLock 的 Redis 实现自带“看门狗”机制:它会定期检查锁是否仍由当前线程持有,并自动续期。避免因为业务处理时间超出锁的初始过期时间,导致锁被提前释放,出现并发问题。

此外,它还支持 RedLock 算法——在多个 Redis 节点上同时获取锁,至少需要 N/2+1 个节点成功才算获锁成功。这种方案适合对一致性要求极高的场景,比如金融交易或订单处理。

适用场景

  • 定时任务防重入:确保集群中只有一个节点执行调度任务。
  • 业务幂等控制:防止重复提交订单、重复扣款。
  • 缓存击穿保护:避免多个实例同时回源查询数据库。
  • 资源互斥访问:文件写入、消息处理等需要排他性的操作。

总的来说,DistributedLock 是一个开箱即用的分布式锁解决方案,API 干净,后端选择丰富。如果你正在构建 .NET 微服务或分布式系统,这个库值得放进工具箱。

本文转载于:https://www.jb51.net/aspnet/348434km8.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注