Files
2026-10-12 16:22:04 +08:00

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}";
}
}
}