.NetCore分布式锁示例

 public interface IDistributedLock
 {
     Task<TResult> ExecuteWithDistributedLockAsync<TResult>(
         string key,
         string value,
         Func<Task<TResult>> func,
         int expiryTimeFromMilliseconds = 1000);
 }

  实现类:

public class RedisLockProvider : IDistributedLock
{
    private readonly IConnectionMultiplexer _connectionMultiplexer;
    private readonly IDatabase _redisDatabase;
    private readonly ILogger<RedisLockProvider> _logger;

    public RedisLockProvider(IConnectionMultiplexer connectionMultiplexer, ILogger<RedisLockProvider> logger)
    {
        _logger = logger;
        _connectionMultiplexer = connectionMultiplexer;
        _redisDatabase = _connectionMultiplexer.GetDatabase();
    }
    public async Task<TResult> ExecuteWithDistributedLockAsync<TResult>(
        string key,
        string value,
        Func<Task<TResult>> func,
        int expiryTimeFromMilliseconds = 1000)
    {
        if (func == null)
            throw new ArgumentNullException(nameof(func));

        var locked = await _redisDatabase.LockTakeAsync(key, value, TimeSpan.FromMilliseconds(expiryTimeFromMilliseconds));

        if (!locked)
        {
            _logger.LogWarning($"Failed to acquire lock for key '{key}'.");
            return default!;
        }

        try
        {
            return await func();
        }
        catch (Exception ex)
        {
            _logger.LogError($"Error occurred while executing {func.Method.Name}, request {JsonConvert.SerializeObject(func.Target)}, ex: {ex.Message}");
            throw;
        }
        finally
        {
            await _redisDatabase.LockReleaseAsync(key, value);
        }
    }
}

说明:

这是一个使用分布式锁(Distributed Lock)的异步方法的示例,该方法使用了异步关键字 asyncawait。让我解释一下这个方法的功能和执行流程:

  1. 方法签名:

    • 方法名:ExecuteWithDistributedLockAsync<TResult>
    • 参数:
      • key: 锁的键(唯一标识锁的资源)
      • value: 锁的值(用于标识当前持有锁的实体)
      • func: 一个返回 Task<TResult> 的异步函数,表示在获取锁之后执行的异步操作
      • expiryTimeFromMilliseconds: 锁的过期时间(毫秒),默认为 1000 毫秒
    • 返回类型:Task<TResult>
  2. 获取分布式锁:

    • 调用 _redisDatabase.LockTakeAsync 方法尝试获取分布式锁,该方法返回一个 Task<bool>,表示是否成功获取锁。
    • 使用 await 等待锁的获取结果。
  3. 锁获取成功:

    • 如果成功获取锁,进入 if (locked) 分支,表示锁已经成功获取。
    • 执行 func() 方法,该方法是作为参数传入的异步函数,返回的是一个泛型结果 Task<TResult>
    • 如果 func() 执行成功,直接返回结果。
  4. 锁获取失败:

    • 如果获取锁失败,输出一条警告日志,并返回默认值(default!)。
  5. 异常处理:

    • 在执行 func() 的过程中,如果发生异常,捕获异常并输出错误日志。
    • 重新抛出捕获的异常。
  6. 释放分布式锁:

    • 无论是否发生异常,都会在 finally 块中调用 _redisDatabase.LockReleaseAsync 方法释放锁。

这个方法主要用于在获取分布式锁的情况下执行异步操作。分布式锁的目的是确保在分布式环境中只有一个实例可以同时执行特定的代码块,以防止并发问题。在这个例子中,func() 表示要在获取锁后执行的异步操作,而 LockReleaseAsync 用于确保在操作完成后释放分布式锁,防止死锁的发生。

调用示例:

     var result = await _distributedLock.ExecuteWithDistributedLockAsync($"{CacheKeys.TeamLockCacheKey(softwareSystem.Name)}_{request.TeamLeaderPhoneNumber}"
         , request.TeamLeaderPhoneNumber, async () =>
         {
             return await _customerAccountClientService.RemoveTeamMemberAsync(softwareSystem.Name, memberId);
         });

 

posted @ 2024-01-29 15:38  明&天  阅读(120)  评论(0)    收藏  举报