redis分布式锁
DistributedMonitor:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DistLocker
{
using StackExchange.Redis;
using System;
using System.Threading.Tasks;
public static class DistributedMonitor
{
private static readonly Lazy<ConnectionMultiplexer> _redis = new Lazy<ConnectionMultiplexer>(() =>
ConnectionMultiplexer.Connect("localhost:6379"));
private static IDatabase Database => _redis.Value.GetDatabase();
// 默认锁过期时间(防止死锁)
private static readonly TimeSpan DefaultLockExpiry = TimeSpan.FromSeconds(30);
/// <summary>
/// 尝试进入分布式锁,最多等待指定时间。
/// </summary>
public static async Task<string> EnterAsync(string key, TimeSpan timeout)
{
if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be empty", nameof(key));
var token = Guid.NewGuid().ToString();
var endTime = DateTime.UtcNow + timeout;
while (DateTime.UtcNow < endTime)
{
bool lockAcquired = await Database.StringSetAsync(
key,
token,
DefaultLockExpiry,
When.NotExists
);
if (lockAcquired)
{
return token; // 成功获得锁
}
await Task.Delay(50); // 等待再尝试
}
return null; // 超时未获得锁
}
/// <summary>
/// 释放锁(仅当当前token匹配时才删除)
/// </summary>
public static async Task<bool> ExitAsync(string key, string token)
{
if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be empty", nameof(key));
if (string.IsNullOrWhiteSpace(token)) throw new ArgumentException("Token cannot be empty", nameof(token));
RedisValue currentToken = await Database.StringGetAsync(key);
if (currentToken == token)
{
return await Database.KeyDeleteAsync(key);
}
return false; // 锁不属于当前请求者,无法释放
}
}
}
使用:
using DistLocker;
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
string key = "distributed_lock_key";
TimeSpan timeout = TimeSpan.FromSeconds(10);
Console.WriteLine("尝试获取锁...");
string token = await DistributedMonitor.EnterAsync(key, timeout);
if (token != null)
{
try
{
Console.WriteLine("成功获取锁,执行临界区操作...");
// 模拟业务逻辑处理
await Task.Delay(2000);
Console.WriteLine("临界区执行完毕");
}
finally
{
bool released = await DistributedMonitor.ExitAsync(key, token);
Console.WriteLine(released ? "锁已释放" : "锁释放失败或已被其他客户端释放");
}
}
else
{
Console.WriteLine("未能在指定时间内获取到锁");
}
Console.WriteLine("程序结束");
Console.ReadLine();
}
}

浙公网安备 33010602011771号