using StackExchange.Redis;
using System;
using System.Threading.Tasks;
public class RedisDistributedLock
{
private readonly IDatabase _database;
private readonly string _lockKey;
private readonly string _uniqueId;
private readonly TimeSpan _expiry;
public RedisDistributedLock(IDatabase database, string lockKey, string uniqueId, TimeSpan expiry)
{
_database = database;
_lockKey = lockKey;
_uniqueId = uniqueId;
_expiry = expiry;
}
public async Task<bool> TryLockAsync()
{
// 尝试获取锁
bool acquired = await _database.StringSetAsync(_lockKey, _uniqueId, _expiry, When.NotExists);
if (acquired)
{
// 如果获取锁成功,开启后台任务自动延长锁的过期时间
Task.Run(async () =>
{
while (true)
{
await Task.Delay(expiry.TotalMilliseconds / 2); // 延长锁的有效时间的一半
if (await _database.StringGetAsync(_lockKey) == _uniqueId)
{
// 只有当锁仍然是当前持有者的时候才尝试延长
await _database.KeyExpireAsync(_lockKey, _expiry);
}
}
});
}
return acquired;
}
public async Task ReleaseLockAsync()
{
// 释放锁的操作,确保只有锁的拥有者才能释放锁
if (await _database.StringGetAsync(_lockKey) == _uniqueId)
{
await _database.KeyDeleteAsync(_lockKey);
}
}
}
var redis = ConnectionMultiplexer.Connect("localhost");
var database = redis.GetDatabase();
var lockKey = "my_lock_key";
var uniqueId = Guid.NewGuid().ToString(); // 生成唯一ID,用于识别锁的拥有者
var expiry = TimeSpan.FromSeconds(10); // 锁的过期时间
var distributedLock = new RedisDistributedLock(database, lockKey, uniqueId, expiry);
if (await distributedLock.TryLockAsync())
{
try
{
// 业务逻辑
}
finally
{
await distributedLock.ReleaseLockAsync();
}
}