在.net core 中,可以使用StackExchange.Redis实现redis分布式锁,
/// <summary>
/// 分布式锁
/// </summary>
/// <param name="Redis">RedisDB</param>
/// <param name="Key">锁标识</param>
/// <param name="Seconds">过期时间(秒)</param>
/// <param name="MilliseSeconds">尝试申请锁时间间隔(毫秒)</param>
public RedisLock(string Key, int Seconds = 60, int MilliseSeconds = 20)
{
key = Key;
value = Guid.NewGuid().ToString();
while (true)
{
bool b = Redis.LockTake(key, value, TimeSpan.FromSeconds(Seconds));
if (b) return;
Thread.Sleep(MilliseSeconds);
}
}
通过使用 Redis.LockTake,尝试对资源(key)加锁,是通过SET lock_key random_value NX PX lock_timeout命令实现的,会尝试设定一个key,其中,NX
确保只有当锁不存在时才设置它,PX
设置锁的过期时间以防止死锁。
所以上面代码,当申请的key已经被加锁了,则申请不成功,就会线程等待(有弊端,如果过期了,还是有可能加上锁,造成同时操作);
当执行完毕后需要释放锁,通过Redis.LockRelease(key, value);这里就能看到value的作用,是为了避免其他人释放锁,只有知道value的才能释放该锁。
/// <summary>
/// 释放锁
/// </summary>
public void Dispose()
{
Redis.LockRelease(key, value);
}
可以将上述方法的类实现IDisposable接口;这样就可以在using语句中自动释放锁啦,具体看using语句和 IDisposable,只有实现了
IDisposable
接口的对象才能在 using
语句中使用。