项目地址
GitHub - samcook/RedLock.net: An implementation of the Redlock algorithm in C#
基本使用
初始化RedLockFactory
var multiplexers = new List<RedLockMultiplexer>
{
ConnectionMultiplexer.Connect("redis1:6379"),
ConnectionMultiplexer.Connect("redis2:6379"),
ConnectionMultiplexer.Connect("redis3:6379")
};
var redlockFactory = RedLockFactory.Create(multiplexers);
乐观锁
不进行阻塞操作,只通过IsAcquired判定是否已经锁了
var resource = "the-thing-we-are-locking-on";
var expiry = TimeSpan.FromSeconds(30);
await 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
}
}
// 当using结束时将自动释放锁
// the lock is automatically released at the end of the using block
悲观锁
进行阻塞操作,直到锁释放,或者等待时间结束(下面的wait)
var resource = "the-thing-we-are-locking-on";
var expiry = TimeSpan.FromSeconds(30);
var wait = TimeSpan.FromSeconds(10);
var retry = TimeSpan.FromSeconds(1);
// blocks until acquired or 'wait' timeout
await using (var redLock = await redlockFactory.CreateLockAsync(resource, expiry, wait, retry)) // there are also non async Create() methods
{
// make sure we got the lock
if (redLock.IsAcquired)
{
// do stuff
}
}
// the lock is automatically released at the end of the using block
依赖注入示例代码
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDistributedLockFactory, RedLockFactory>(
x => RedLockFactory.Create(/* endpoints */)
);
}
public class MyClass
{
private readonly IDistributedLockFactory factory;
public MyClass(IDistributedLockFactory factory)
{
this.factory = factory;
}
public void DoSomething()
{
using (var redlock = this.factory.CreateLock("foo", TimeSpan.FromSeconds(30)))
{
if (redlock.IsAcquired) { /* ... */ }
}
}
}
Moq Test
[Test]
public void Test()
{
var mockRedLock = new Mock<IRedLock>();
mockRedLock.Setup(x => x.IsAcquired).Returns(true);
var mockFactory = new Mock<IDistributedLockFactory>();
mockFactory.Setup(x => x.CreateLock(It.IsAny<string>(), It.IsAny<TimeSpan>())).Returns(mockRedLock.Object);
var subject = new MyClass(mockFactory.Object);
subject.DoSomething();
Assert.That(/* whatever */);
}