176 lines
4.6 KiB
C#
176 lines
4.6 KiB
C#
using Microsoft.Extensions.Logging;
|
|
|
|
namespace RedisHelper
|
|
{
|
|
public class DistributedLock : IDistributedLock
|
|
{
|
|
private readonly ICache _cache;
|
|
private readonly ILogger<DistributedLock> _logger;
|
|
|
|
public DistributedLock(ICache cache, ILogger<DistributedLock> logger)
|
|
{
|
|
_cache = cache;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<T> TryExecuteAsync<T>(string key, Func<Task<T>> action, int expiry = 30, bool retry = false, int retryDelay = 100)
|
|
{
|
|
string lockKey = GetLockKey(key);
|
|
string lockValue = Guid.NewGuid().ToString();
|
|
|
|
while (true)
|
|
{
|
|
if (TryAcquireLock(lockKey, lockValue, expiry))
|
|
{
|
|
try
|
|
{
|
|
return await action();
|
|
}
|
|
finally
|
|
{
|
|
ReleaseLock(lockKey, lockValue);
|
|
}
|
|
}
|
|
|
|
if (!retry)
|
|
{
|
|
return default(T);
|
|
}
|
|
|
|
await Task.Delay(retryDelay);
|
|
}
|
|
}
|
|
|
|
public async Task<bool> TryExecuteAsync(string key, Func<Task> action, int expiry = 30, bool retry = false, int retryDelay = 100)
|
|
{
|
|
string lockKey = GetLockKey(key);
|
|
string lockValue = Guid.NewGuid().ToString();
|
|
|
|
while (true)
|
|
{
|
|
if (TryAcquireLock(lockKey, lockValue, expiry))
|
|
{
|
|
try
|
|
{
|
|
await action();
|
|
return true;
|
|
}
|
|
finally
|
|
{
|
|
ReleaseLock(lockKey, lockValue);
|
|
}
|
|
}
|
|
|
|
if (!retry)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
await Task.Delay(retryDelay);
|
|
}
|
|
}
|
|
|
|
public T TryExecute<T>(string key, Func<T> action, int expiry = 30, bool retry = false, int retryDelay = 100)
|
|
{
|
|
string lockKey = GetLockKey(key);
|
|
string lockValue = Guid.NewGuid().ToString();
|
|
|
|
while (true)
|
|
{
|
|
if (TryAcquireLock(lockKey, lockValue, expiry))
|
|
{
|
|
try
|
|
{
|
|
return action();
|
|
}
|
|
finally
|
|
{
|
|
ReleaseLock(lockKey, lockValue);
|
|
}
|
|
}
|
|
|
|
if (!retry)
|
|
{
|
|
return default(T);
|
|
}
|
|
|
|
Thread.Sleep(retryDelay);
|
|
}
|
|
}
|
|
|
|
public bool TryExecute(string key, Action action, int expiry = 30, bool retry = false, int retryDelay = 100)
|
|
{
|
|
string lockKey = GetLockKey(key);
|
|
string lockValue = Guid.NewGuid().ToString();
|
|
|
|
while (true)
|
|
{
|
|
if (TryAcquireLock(lockKey, lockValue, expiry))
|
|
{
|
|
try
|
|
{
|
|
action();
|
|
return true;
|
|
}
|
|
finally
|
|
{
|
|
ReleaseLock(lockKey, lockValue);
|
|
}
|
|
}
|
|
|
|
if (!retry)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Thread.Sleep(retryDelay);
|
|
}
|
|
}
|
|
|
|
private bool TryAcquireLock(string lockKey, string lockValue, int expiry)
|
|
{
|
|
try
|
|
{
|
|
var redis = _cache.GetFullRedis();
|
|
|
|
bool acquired = redis.Add(lockKey, lockValue, expiry);
|
|
|
|
if (acquired)
|
|
{
|
|
}
|
|
|
|
return acquired;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, $"获取分布式锁时发生错�? {lockKey}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private void ReleaseLock(string lockKey, string lockValue)
|
|
{
|
|
try
|
|
{
|
|
var redis = _cache.GetFullRedis();
|
|
|
|
var currentValue = redis.Get<string>(lockKey);
|
|
|
|
if (currentValue == lockValue)
|
|
{
|
|
redis.Remove(lockKey);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, $"释放分布式锁时发生错�? {lockKey}");
|
|
}
|
|
}
|
|
|
|
private string GetLockKey(string key)
|
|
{
|
|
return $"{key}";
|
|
}
|
|
}
|
|
}
|