要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁、进程锁。
线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。
进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源。
分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。
设计思路
由于Redis是单线程模型,命令操作原子性,所以利用这个特性可以很容易的实现分布式锁。
A用户端在Resdis写入1个KEY,其他的用户无法写入这个KEY,实现锁的效果。
A用户使用完成后释放KEY,或者是KEY过了超时时间,释放KEY。
主要代码
Boolean isLoading = dataPermissionRedis.TryLoading(a, b);
if (isLoading)
{
try
{
//todo
}
finally
{
dataPermissionRedis.removeLoading(a, b);
}
}
public bool TryLoading(string a, string b, int expireTime = 20)
{
var key = GetLoadingKey(a, b);
using (IRedisClient client = this.GetClient())
{
var r = client.Add(key, "1", new TimeSpan(0, 0, 0, expireTime));
//存在
if (!r)
{
//获取过期时间
var totalSeconds = client.GetTimeToLive(key)?.TotalSeconds;
//存在且过期时间大于 expireTime(当做永久key) 解决历史遗留key
if (totalSeconds.HasValue && totalSeconds.Value > expireTime)
{
//强制设置过期时间
client.ExpireEntryIn(key, new TimeSpan(0, 0, 0, expireTime));
}
}
return r;
}
}
public void removeLoading(string a, string b)
{
using (IRedisClient client = this.GetClient())
{
client.Remove(GetLoadingKey(a, b));
}
}