Redlock在一些不同进程必须操作共享资源的环境中特别适用。
实现DLM(Distributed Lock Manager)官方链接
一、安装
Install-Package RedLock.net -Version 2.0.0
二、使用
- 通过一组Redis终端构造一个RedLockFactory.
- 在程序中重复使用RedLockFactory。每一个实例维持它自己配置中的连接。当你的应用停用时记得处理它。
- 用工厂在一个代码块中创建一个RedLock,保证在运行任何action之前,锁在代码块中是已被获取的。
- RedLock有个timer设置特定时间自动释放redis锁,以避免Redis宕机造成死锁。
具体代码:
1.连接Redis端,获取工厂
var endPoints = new List<RedLockEndPoint>
{
new DnsEndPoint("redis1", 6379),
new DnsEndPoint("redis2", 6379),
new DnsEndPoint("redis3", 6379)
};
var redlockFactory = RedLockFactory.Create(endPoints);
如果你需要更多更具体的配置(比如 password,SSL,connection timeout等)你可以使用RedLockEndPoint类或RedLockMultiplexer类。
2.工厂创建分布式锁
var resource = "the-thing-we-are-locking-on";
var expiry = TimeSpan.FromSeconds(30);
using (var redLock = await redlockFactory.CreateLockAsync(resource, expiry)) // there are also non async Create() methods
{
// make sure we got the lock
if (redLock.IsAcquired)
{
// do stuff
}
}
在使用步骤中提到需要注意你的应用程序结束后需要dispose掉factory和redlock。所以程序中最好是用using包围。
三、算法
(以下为笔者粗略的翻译和理解,有些不解地方以后运用的时候慢慢去研究)
为了获得锁,客户端实现以下步骤:
1. 获取当前时间的毫秒值;
2. 试图在N个连续的实例中获取锁,用相同的key名和随机的值。在步奏2里,当在每个实例中设置了锁,客户端为了得到锁,使用的超时小于总的锁自动释放时间。这是为了防止客户端与下一个Redis端通话的阻塞时间过长。
3. 客户端计通过减去当前时间(在第一步得到的时间戳)计算出运行时间,以获取锁。当且仅当客户端能够在多实例中获得锁,那总的运行时间少于锁的有效时间,则锁可以被索取。
4. 如果获取到了锁,她的有效时间=最初有效时间-运行时间
5. 如果客户端由于某些原因获取锁失败,它将会尝试去解锁所有的实例