DistributedLock

DistributedLock

多技术支持的分布式同步库

DistributedLock是一个.NET库,提供分布式互斥锁、读写锁和信号量功能。它简化了跨应用程序和机器的代码同步访问。该库支持多种底层技术,包括SQL Server、PostgreSQL、MySQL、Oracle、Redis和Azure等。DistributedLock提供简洁的API和依赖注入支持,适合在分布式环境中需要资源同步的.NET开发场景。

DistributedLock分布式锁.NET库同步原语多应用同步Github开源项目

DistributedLock

DistributedLock是一个.NET库,基于各种底层技术提供了健壮且易用的分布式互斥锁、读写锁和信号量。

使用DistributedLock,在多个应用程序/机器之间同步访问代码区域变得非常简单:

await using (await myDistributedLock.AcquireAsync()) { // 我在这里持有锁 }

实现

DistributedLock包含基于各种技术的实现;你可以单独安装实现包,也可以直接安装DistributedLock NuGet包 NuGet状态,这是一个"元"包,包含所有实现作为依赖项。注意每个包都根据SemVer独立进行版本控制

点击上面任何包的名称查看该实现的具体文档,或继续阅读适用于所有实现的通用文档。

DistributedLock.Core NuGet状态包含公共代码和抽象,被所有实现引用。

同步原语

  • 锁: 提供对代码区域的独占访问
  • 读写锁: 具有多级访问权限的锁。锁可以同时被任意数量的"读取者"持有,或被单个"写入者"持有。
  • 信号量: 类似于锁,但可以同时被最多N个用户持有,而不仅仅是一个。

虽然所有实现都支持锁,但其他原语只被某些实现支持。有关详细信息,请参阅特定实现的文档页面

基本用法

名称

由于分布式锁(和其他分布式同步原语)不局限于单个进程,它们的身份基于通过构造函数提供的名称。不同的底层技术对名称格式有不同的限制;然而,DistributedLock在很大程度上允许你忽略这些限制,通过转义/散列否则无效的名称。

Acquire

所有同步原语都支持相同的基本访问模式。Acquire方法返回一个"句柄"对象,表示持有锁。当句柄被处置时,锁被释放:

var myDistributedLock = new SqlDistributedLock(name, connectionString); // 例如,如果我们使用SQL Server using (myDistributedLock.Acquire()) { // 我们在这里持有锁 } // using块的隐式Dispose()调用在这里释放它

TryAcquire

虽然Acquire会阻塞直到锁可用,但还有一个TryAcquire变体,如果无法获取锁(因为被其他地方持有),则返回null

using (var handle = myDistributedLock.TryAcquire()) { if (handle != null) { // 我们获得了锁 :-) } else { // 其他人持有它 :-( } }

async支持

这两种方法的async版本也受支持。当你编写异步代码时,这些方法是首选,因为它们在等待锁时不会消耗线程。如果你使用C#8或更高版本,你还可以异步处置句柄:

超时

await using (await myDistributedLock.AcquireAsync()) { ... }

此外,所有这些方法都支持可选的timeout参数。timeout决定了Acquire在失败并抛出TimeoutException之前等待的时间,以及TryAcquire在返回null之前等待的时间。Acquire的默认timeoutTimeout.InfiniteTimeSpan,而TryAcquire的默认timeoutTimeSpan.Zero

取消

最后,这些方法接受一个可选的CancellationToken参数,允许通过取消来中断获取操作。请注意,一旦获取成功,这不会取消对锁的持有。

提供者

对于使用依赖注入的应用程序,DistributedLock的提供者使得将锁(或其他原语)的名称规范与其他设置(如数据库连接字符串)分离变得容易。例如,在ASP.NET Core应用中,你可能这样做:

// 在你的Startup.cs中: services.AddSingleton<IDistributedLockProvider>(_ => new PostgresDistributedSynchronizationProvider(myConnectionString)); services.AddTransient<SomeService>(); // 在SomeService.cs中 public class SomeService { private readonly IDistributedLockProvider _synchronizationProvider; public SomeService(IDistributedLockProvider synchronizationProvider) { this._synchronizationProvider = synchronizationProvider; } public void InitializeUserAccount(int id) { // 使用提供者构造一个锁 var @lock = this._synchronizationProvider.CreateLock($"UserAccount{id}"); using (@lock.Acquire()) { // 做一些事情 } // 或者,对于常见用例,扩展方法允许通过单个调用完成此操作 using (this._synchronizationProvider.AcquireLock($"UserAccount{id}")) { // 做一些事情 } } }

其他主题

贡献

欢迎贡献!如果你有兴趣为新的或现有的问题做出贡献,请通过问题评论让我知道,这样我可以帮助你入门并避免你浪费精力。

在本地使用存储库的设置步骤记录在这里

发布说明

  • 2.5
    • 新增支持通过 DbDataSource 创建 Postgres 锁,这对使用 NpgsqlMultiHostDataSource 的应用很有帮助。感谢 davidngjy 的实现! (#153, DistributedLock.Postgres 1.2.0)
    • 升级 Npgsql 到 8.0.3 以避免漏洞。感谢 @Meir017/@davidngjy 的实现! (#218, DistributedLock.Postgres 1.2.0)
    • 修复启用连接保活时 Postgres 的竞态条件 (#216, DistributedLock.Core 1.0.7)
    • 升级 Microsoft.Data.SqlClient 到 5.2.1 以避免漏洞 (#210, DistributedLock.SqlServer 1.0.5)
  • 2.4
    • 新增支持在 Postgres 中使用 pg_advisory_xact_lock 进行事务范围锁定,这对使用 PgBouncer 很有帮助 (#168, DistributedLock.Postgres 1.1.0)
    • 改进对较新版本 StackExchange.Redis 的支持,尤其是在使用默认积压策略时 (#162, DistributedLock.Redis 1.0.3)。感谢 @Bartleby2718 的帮助!
    • 放弃对 net461 的支持 (仍然支持 net462)。感谢 @Bartleby2718 的实现!
    • 减少库抛出的 UnobservedTaskException 的发生 (#192, DistributedLock.Core 1.0.6)
    • 将依赖项更新到没有已知问题/漏洞的现代版本 (#111/#177/#184/#185, 所有包)。感谢 @Bartleby2718 的帮助!
    • 改进在 Linux/.NET 8 上 FileDistributedLock 的目录创建并发处理 (#195, DistributedLock.FileSystem 1.0.2)
    • 允许在 SQL Server 中使用事务范围锁而无需显式禁用多路复用 (#189, DistributedLock.SqlServer 1.0.4)
    • dndocs 上新的 API 文档。感谢 @NeuroXiq!
    • 新的贡献者文档,指导如何在本地运行项目(参见 Contributing)
  • 2.3.4
  • 2.3.3
    • 由于漏洞更新 Microsoft.Data.SqlClient (#149, DistributedLock.SqlServer 1.0.3)
    • 由于漏洞更新 Oracle.ManagedDataAccess 和 Oracle.ManagedDataAccess.Core 的版本 (DistributedLock.Oracle 1.0.2)
  • 2.3.2
    • 解决使用短暂非零超时等待 Postgres 建议锁时底层的竞态条件 (#147, DistributedLock.Postgres 1.0.4)。感谢 @Tzachi009 报告和隔离这个问题!
  • 2.3.1
    • 修复关系数据库锁的 HandleLostToken 并发问题 (#133, DistributedLock.Core 1.0.5, DistributedLock.MySql 1.0.1, DistributedLock.Oracle 1.0.1, DistributedLock.Postgres 1.0.3, DistributedLock.SqlServer 1.0.2)。感谢 @OskarKlintrot 的测试!
    • 修复在 Redis 中尝试禁用自动延期时的误导性错误消息 (#130, DistributedLock.Redis 1.0.2)
    • 修复取消 WaitHandle 的异步等待的并发问题 (#120, DistributedLock.WaitHandles 1.0.1)
  • 2.3.0
    • 新增基于 Oracle 的实现 (#45, DistributedLock.Oracle 1.0.0)。感谢 @odin568 的测试!
    • 使基于文件的锁定对瞬态 UnauthorizedAccessException 更具鲁棒性 (#106 & #109, DistributedLock.FileSystem 1.0.1)
    • 解决 Npgsql 命令准备中的取消错误 (#112, DistributedLock.Postgres 1.0.2)
  • 2.2.0
    • 新增基于 MySQL/MariaDB 的实现 (#95, DistributedLock.MySql 1.0.0)。感谢 @theplacefordev 的测试!
  • 2.1.0
    • 新增基于 ZooKeeper 的实现 (#41, DistributedLock.ZooKeeper 1.0.0)
  • 2.0.2
    • 修复在使用保活的 SqlServer 或 Postgres 锁句柄上访问 HandleLostToken 时会挂起的错误 (#85, DistributedLock.Core 1.0.1)
    • 修复在使用多路复用的 SqlServer 或 Postgres 锁时,损坏的数据库连接可能导致未来的锁尝试失败的错误 (#83, DistributedLock.Core 1.0.1)
    • 更新 Npgsql 依赖到 5.x 以利用各种错误修复 (#61, DistributedLock.Postgres 1.0.1)
  • 2.0.1
    • 修复使用 WithKeyPrefix 的数据库时 Redis 锁的行为 (#66, DistributedLock.Redis 1.0.1)。感谢 @skomis-mm 的贡献!
  • 2.0.0 (另请参阅 从 1.x 迁移到 2.x)
    • 重新设计了包结构,现在 DistributedLock 是一个伞形包,每种实现技术都有自己的包 (重大变更)
    • 新增基于 Postgresql 的锁定 (#56, DistributedLock.Postgres 1.0.0)
    • 新增基于 Redis 的锁定 (#24, DistributedLock.Redis 1.0.0)
    • 新增基于 Azure blob 的锁定 (#42, DistributedLock.Azure 1.0.0)
    • 新增基于文件的锁定 (#28, DistributedLock.FileSystem 1.0.0)
    • 新增提供者类以改进 IOC 集成 (#13)
    • 为程序集添加强名称。感谢 @pedropaulovc 的贡献! (#47, 重大变更)
    • 使锁句柄实现 IAsyncDisposableIDisposable #20, 重大变更)
    • 为所有同步原语公开与实现无关的接口 (例如 IDistributedLock) (#10)
    • 新增 HandleLostToken API 用于跟踪锁的底层连接是否断开 (#6, 重大变更)
    • 新增 SourceLink 支持 (#57)
    • 移除 GetSafeName API,改为默认安全命名 (重大变更)
    • 将 "SystemDistributedLock" 重命名为 "EventWaitHandleDistributedLock" (DistributedLock.WaitHandles 1.0.0)
    • 停止支持 net45 (重大变更)
    • SqlDistributedLock 中移除 DbConnectionDbTransaction 构造函数,保留接受 IDbConnection/IDbTransaction 的构造函数 (#35, 重大变更)
    • 将返回 Task<IDisposable> 的方法改为返回 ValueTask,使得 using (@lock.AcquireAsync()) { ... } 在没有 await 的情况下不再编译 (#34, 重大变更)
    • UpgradeableLockHandle.UpgradeToWriteLock 改为返回 void (#33, 重大变更)
    • 对所有目标框架默认切换到 Microsoft.Data.SqlClient (重大变更)
    • 将所有锁定实现更改为非可重入 (重大变更)
  • 1.5.0
    • 通过 Microsoft.Data.SqlClient 添加跨平台支持 (#25)。此功能适用于 .NET Standard >= 2.0。感谢 @alesebi91 帮助实现和测试!
    • 添加 C#8 可空注释 (#31)
    • 修复连接多路复用中的小错误,该错误可能导致更多锁争用 (#32)
  • 1.4.0
    • 添加基于 SQL 的分布式信号量 (#7)
    • 修复 SqlDistributedLockConnectionStrategy.Azure 会泄漏连接的错误,依赖 GC 回收它们 (#14)。感谢 zavalita1 调查此问题!
    • 在检测到死锁时抛出特定异常类型 (DeadlockException),而不是通用的 InvalidOperationException (#11)
  • 1.3.1 小修复,避免在基于事务的锁中"泄漏"隔离级别更改 ([#

编辑推荐精选

iTerms

iTerms

企业专属的AI法律顾问

iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。

SimilarWeb流量提升

SimilarWeb流量提升

稳定高效的流量提升解决方案,助力品牌曝光

稳定高效的流量提升解决方案,助力品牌曝光

Sora2视频免费生成

Sora2视频免费生成

最新版Sora2模型免费使用,一键生成无水印视频

最新版Sora2模型免费使用,一键生成无水印视频

Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

AI助手热门AI工具AI创作AI辅助写作讯飞绘文内容运营个性化文章多平台分发
TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

热门AI工具生产力协作转型TraeAI IDE
商汤小浣熊

商汤小浣熊

最强AI数据分析助手

小浣熊家族Raccoon,您的AI智能助手,致力于通过先进的人工智能技术,为用户提供高效、便捷的智能服务。无论是日常咨询还是专业问题解答,小浣熊都能以快速、准确的响应满足您的需求,让您的生活更加智能便捷。

imini AI

imini AI

像人一样思考的AI智能体

imini 是一款超级AI智能体,能根据人类指令,自主思考、自主完成、并且交付结果的AI智能体。

Keevx

Keevx

AI数字人视频创作平台

Keevx 一款开箱即用的AI数字人视频创作平台,广泛适用于电商广告、企业培训与社媒宣传,让全球企业与个人创作者无需拍摄剪辑,就能快速生成多语言、高质量的专业视频。

即梦AI

即梦AI

一站式AI创作平台

提供 AI 驱动的图片、视频生成及数字人等功能,助力创意创作

下拉加载更多