【问题标题】:Distributed lock is not working with RedLock.net分布式锁不适用于 RedLock.net
【发布时间】:2021-01-20 22:34:38
【问题描述】:

我想用 Redis 做分布式锁。我为此使用RedLock.net nuget 包。 但是线程能够获取锁,甚至另一个线程已经获取了锁。

这里是示例代码:

public void Demo(RedLockFactory redLockFactory)
        {
            Parallel.For(0, 5, x =>
            {
                TimeSpan expiry = TimeSpan.FromSeconds(30);
                var wait = TimeSpan.FromSeconds(10);
                var retry = TimeSpan.FromSeconds(1);

                string user = $"User:{x}";
                using (var redLock = redLockFactory.CreateLock(resource, expiry, wait, retry))
                {

                    // make sure we got the lock
                    if (redLock.IsAcquired)
                    {
                        Console.WriteLine($"{user} acquired lock at {DateTimeOffset.Now.ToString("dd-MM-yyyy HH:mm:ss")}.");
                    }
                    else
                    {
                        Console.WriteLine($"{user} didn't get the lock.");
                    }
                }
            });
        }

这是我的演示输出

User:4 acquired lock at 06-10-2020 09:24:34.
User:2 acquired lock at 06-10-2020 09:24:34.
User:1 acquired lock at 06-10-2020 09:24:34.
User:0 acquired lock at 06-10-2020 09:24:35.
User:3 acquired lock at 06-10-2020 09:24:35.

如您所见,每个线程都能够获得锁,这是不应该发生的。

一旦获得锁,其他线程应该无法获得锁。

【问题讨论】:

    标签: c# asp.net-core redis stackexchange.redis redlock.net


    【解决方案1】:

    根据RedLock.net/README.md,“锁在 using 块结束时自动释放”。

    所以我认为您的演示输出中发生的是:

    1. 五个线程并行启动,每个线程都尝试锁定同一资源。
    2. 线程 4 获胜(成功获得其锁)并执行以下操作;同时,其他线程等待(最多 10 秒):
      • 将“获得的锁”写入控制台
      • 离开using 块,释放它的锁(现在另一个线程可以获胜)
    3. 线程 2 获胜并在其余线程等待时执行相同操作。
    4. 线程 1、0 和 3 同上。
    5. 每个线程都快速完成工作,因此没有线程在 10 秒内无法获得锁。

    如果您想看到锁获取失败,请在退出 using 块之前执行非常慢的操作(>10 秒)。出于演示目的,您可以在编写“已获取”行后Thread.Sleep(15000)

    【讨论】:

    • 那我想,它不符合分布式锁的定义。如果我的应用程序有多个实例,那么所有线程将能够同时获取锁。
    • 一次只有一个线程成功获得资源锁。在您的演示中,线程碰巧都是本地的,但如果线程分布在多个实例中,您会看到相同的行为。
    • 更多信息:调用 CreateLock 时,会从一组 Redis 服务器的仲裁中获得一个锁。 (参见Start() in RedLock.cs)当退出 using 块时,C# 调用redLock.Dispose(),并在 Redis 服务器之间释放锁。 (见Dispose() in RedLock.cs
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-19
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多