RedLock.net

项目地址

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 */);
}