Project Icon

DistributedLock

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

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

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 小修复,避免在基于事务的锁中"泄漏"隔离级别更改 ([#
项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

稿定AI

稿定设计 是一个多功能的在线设计和创意平台,提供广泛的设计工具和资源,以满足不同用户的需求。从专业的图形设计师到普通用户,无论是进行图片处理、智能抠图、H5页面制作还是视频剪辑,稿定设计都能提供简单、高效的解决方案。该平台以其用户友好的界面和强大的功能集合,帮助用户轻松实现创意设计。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号