梅琴 發表於 2025-8-29 09:28:11

DistributedLock 实现.Net分布式锁功能

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">什么是 DistributedLock</a></li><li><a href="#_label1">基本使用</a></li><li><a href="#_label2">安装 NuGet 包</a></li><li><a href="#_label3">使用 Redis 分布式锁</a></li><li><a href="#_label4">使用 SQL Server 分布式锁</a></li><li><a href="#_label5">依赖注入集成</a></li><li><a href="#_label6">续租机制与 RedLock</a></li><li><a href="#_label7">适用场景</a></li></ul></div><p>在分布式系统中,经常会遇到多个实例同时访问同一份资源的情况,例如:</p>
<ul><li>多个服务节点同时写入数据库同一行数据</li><li>定时任务在多个节点上同时运行,导致重复执行</li><li>多实例写缓存时出现数据覆盖问题</li></ul>
<p>为了解决&nbsp;<strong>并发冲突</strong>&nbsp;和&nbsp;<strong>数据一致性</strong>&nbsp;问题,就需要用到&nbsp;<strong>分布式锁</strong>。</p>
<p>今天给大家介绍一个 .NET 里非常好用的分布式锁库 &mdash;&mdash;&nbsp;<strong>DistributedLock</strong>。</p>
<p class="maodian"><a name="_label0"></a></p><h2>什么是 DistributedLock</h2>
<p>DistributedLock&nbsp;是一个轻量级、线程安全的 .NET 库,用来在分布式环境下实现锁的功能。支持多种后端存储,包括:</p>
<ul><li><strong>Redis</strong></li><li>&nbsp;<strong>SQL Server</strong></li><li>&nbsp;<strong>PostgreSQL</strong></li><li>&nbsp;<strong>MySQL</strong></li><li>&nbsp;<strong>MongoDB</strong></li><li>&nbsp;<strong>内存模式(本地锁)</strong></li></ul>
<p>只需要更换存储提供程序,就能无缝地在不同的环境下使用。</p>
<p class="maodian"><a name="_label1"></a></p><h2>基本使用</h2>
<p class="maodian"><a name="_label2"></a></p><h2>安装 NuGet 包</h2>
<p>在项目中引入需要的后端依赖,如:</p>
<div class="jb51code"><pre class="brush:csharp;">dotnet add package DistributedLock--包含所有实现的元包
dotnet add package DistributedLock.Redis
dotnet add package DistributedLock.SqlServer</pre></div>
<p>(Redis 和 SQL Server 是最常见的场景,也可以选择别的实现)</p>
<p class="maodian"><a name="_label3"></a></p><h2>使用 Redis 分布式锁</h2>
<div class="jb51code"><pre class="brush:csharp;">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 have the lock */ }
}</pre></div>
<p>只要使用&nbsp;Acquire&nbsp;/&nbsp;AcquireAsync&nbsp;获取锁,代码块执行完毕后会自动释放,非常优雅。</p>
<p class="maodian"><a name="_label4"></a></p><h2>使用 SQL Server 分布式锁</h2>
<div class="jb51code"><pre class="brush:csharp;">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())
      }
    }
}</pre></div>
<p>在&nbsp;<strong>定时任务(Quartz、Hangfire 等)</strong>&nbsp;场景中,特别适合用来避免多节点重复执行。</p>
<p class="maodian"><a name="_label5"></a></p><h2>依赖注入集成</h2>
<p>appsettings.json</p>
<div class="jb51code"><pre class="brush:json;">{
"ConnectionStrings": {
    "SqlServer": "Server=myServerAddress;Database=Locks;User Id=myUsername;Password=myPassword;",
    "Redis": "localhost:6379"
}
}</pre></div>
<p>DistributedLock 支持依赖注入,适合在项目中使用。</p>
<div class="jb51code"><pre class="brush:csharp;">// Startup.cs 或 Program.cs
public void ConfigureServices(IServiceCollection services)
{
    var connectionString = Configuration.GetConnectionString("SqlServer");
    services.AddSingleton&lt;IDistributedLockProvider&gt;(_ =&gt;
      new SqlDistributedSynchronizationProvider(connectionString));
    services.AddTransient&lt;SomeService&gt;();
}
// 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(#34;UserAccount{id}");
      await using (await @lock.AcquireAsync())
      {
            // 执行需要同步的操作
            Console.WriteLine(#34;Initializing user account {id}...");
            await Task.Delay(1000);
      }
    }
}</pre></div>
<p class="maodian"><a name="_label6"></a></p><h2>续租机制与 RedLock</h2>
<p>DistributedLock 的 Redis 实现内置了&ldquo;看门狗&rdquo;机制,定期检查锁是否仍由当前线程持有,并自动延长锁的过期时间,避免因业务处理时间过长导致锁失效。</p>
<p>DistributedLock 的 Redis 实现支持 RedLock 算法,通过在多个 Redis 节点上获取锁(至少 N/2+1 个节点)来确保高可靠性。RedLock 适合对一致性要求极高的场景。</p>
<p class="maodian"><a name="_label7"></a></p><h2>适用场景</h2>
<ul><li><strong>定时任务防重入</strong>(保证只有一个节点执行)</li><li><strong>业务幂等控制</strong>(防止重复提交订单)</li><li><strong>缓存击穿保护</strong>(避免多个实例同时回源数据库)</li><li><strong>资源互斥访问</strong>(文件写入、消息处理等)</li></ul>
<p>DistributedLock&nbsp;是一个简单易用的分布式锁库,支持多种后端,特别适合用在微服务和分布式任务中。</p>
<p>如果你正在开发&nbsp;<strong>分布式系统</strong>,强烈建议把它加入到你的工具库里。</p>
<p>原文链接:<a href="https://www.toutiao.com/article/7543141797447352882/?app=news_article&share_uid=MS4wLjABAAAAJ4ODhsAfbLSJ3_7WT4p4P4TFQN5GsfRMRJEbrNUZJDB4LZHjYvN_eR6t2TOY0pPc&category_new=__all__&req_id_new=202508280643531AEE4A86D20DC400353F&timestamp=1756339865&share_did=MS4wLjACAAAAzT0vZ_h7G83TsHPz_2fSP7NgaCpIM9LMCkrp3X3Idy9PGE2iiy-f0z6fh1BJKD0L&upstream_biz=client_share&share_token=833D92FF-A0B1-49B8-B000-D9D3F8920BBA&tt_from=weixin&utm_source=weixin&utm_medium=toutiao_ios&utm_campaign=client_share&wxshare_count=1&source=m_redirect" rel="external nofollow" target="_blank" title="DistributedLock 实现.Net分布式锁">DistributedLock 实现.Net分布式锁</a></p>
頁: [1]
查看完整版本: DistributedLock 实现.Net分布式锁功能