项目

分布式锁

分布式锁是一种用于管理多个应用程序尝试访问同一资源的技术。其主要目的是确保在任意时刻,多个应用程序中只有一个能够访问同一资源。否则,不同应用程序同时访问同一对象可能导致资源数据损坏。

ABP框架当前的分布式锁实现基于DistributedLock库。

安装

打开命令行终端,输入以下命令将Volo.Abp.DistributedLocking包安装到您的项目中:

abp add-package Volo.Abp.DistributedLocking

该包提供了使用分布式锁系统所需的API,但在使用前需要配置提供程序。

配置提供程序

DistributedLock库为锁机制提供了多种实现方案,例如RedisZooKeeper

若需使用Redis提供程序,请先向项目添加DistributedLock.Redis NuGet包,然后在ABP模块类的ConfigureServices方法中加入以下代码:

using Medallion.Threading;
using Medallion.Threading.Redis;

namespace AbpDemo
{
    [DependsOn(
            typeof(AbpDistributedLockingModule)
            //如有其他依赖项,请在此处添加
    )]
    public class MyModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var configuration = context.Services.GetConfiguration();
        
            context.Services.AddSingleton<IDistributedLockProvider>(sp =>
            {
                var connection = ConnectionMultiplexer
                    .Connect(configuration["Redis:Configuration"]);
                return new 
                    RedisDistributedSynchronizationProvider(connection.GetDatabase());
            });
        }
    }
}

此代码从配置中获取Redis连接字符串,因此需在appsettings.json文件中添加以下配置:

"Redis": {
    "Configuration": "127.0.0.1"
}

使用方式

分布式锁API有两种使用方式:通过ABP的IAbpDistributedLock抽象接口,或直接使用DistributedLock库的API。

使用IAbpDistributedLock服务

IAbpDistributedLock是ABP为简化分布式锁使用而提供的轻量级服务。

示例:使用IAbpDistributedLock.TryAcquireAsync方法

using Volo.Abp.DistributedLocking; 

namespace AbpDemo
{
    public class MyService : ITransientDependency
    {
        private readonly IAbpDistributedLock _distributedLock;
  public MyService(IAbpDistributedLock distributedLock)
        {
            _distributedLock = distributedLock;
        }
        
        public async Task MyMethodAsync()
        {
            await using (var handle = 
                         await _distributedLock.TryAcquireAsync("MyLockName"))
            {
                if (handle != null)
                {
                    // 访问共享资源的代码
                }
            }   
        }
    }
}

TryAcquireAsync方法可能无法获取锁。若获取失败将返回null,此时不应访问资源。当句柄非空时,表示已获得锁,可安全访问资源。

该方法接收以下参数:

  • namestring,必需):锁的唯一名称。不同命名的锁用于访问不同资源。
  • timeoutTimeSpan):获取锁的等待超时时间。默认值为TimeSpan.Zero,表示若锁已被其他应用持有则立即返回。
  • cancellationToken:可用于取消操作的取消令牌。

配置

AbpDistributedLockOptions

AbpDistributedLockOptions是配置分布式锁的主选项类。

示例:为应用程序设置分布式锁键前缀

Configure<AbpDistributedLockOptions>(options =>
{
    options.KeyPrefix = "MyApp1";
});

请将上述代码写入模块类ConfigureServices方法中。

可用选项
  • KeyPrefix (string, 默认值: null): 指定锁名称前缀。

使用DistributedLock库API

ABP的IAbpDistributedLock服务功能有限,主要供框架内部使用。实际开发中建议直接使用DistributedLock库的原生API,详见其官方文档

Volo.Abp.DistributedLocking.Abstractions包

如果您正在开发可复用库或应用模块,可能不希望为单实例运行的简单应用引入额外依赖。此时,您的库可以依赖Volo.Abp.DistributedLocking.Abstractions包。该包定义了IAbpDistributedLock服务并以进程内方式实现(非真正分布式)。通过这种方式,您的库可在单实例应用中正常运行(无需分布式锁提供程序依赖)。当应用部署到集群环境时,开发者应按安装章节说明安装实际的分布式提供程序。

在本文档中