.NET Core 基于 Redis 实现分布式锁原理解析

.NET Core 基于 Redis 实现分布式锁的原理是调用 redis 的 SETNX 命令,若键 key 已经存在, 则 SETNX 命令不做任何动作。命令在设置成功时返回 1 , 设置失败时返回 0 。
http://redisdoc.com/string/setnx.html
新建一个 .NET Core 3.1 的控制台项目,添加 StackExchange.Redis 引用,nuget命令如下:

Install-Package StackExchange.Redis -Version 2.1.58

我们调用类库的 StringSet 方法,通过 StackExchange.Redis 源码,可以看到 StringSet 方法会调用 GetStringSetMessage 私有的方法,通过 when 的枚举值,来执行不同的 set 命令,代码如下:

if (expiry == null || expiry.Value == TimeSpan.MaxValue)

            { // no expiry

                switch (when)

                {

                    case When.Always: return Message.Create(Database, flags, RedisCommand.SET, key, value);

                    case When.NotExists: return Message.Create(Database, flags, RedisCommand.SETNX, key, value);

                    case When.Exists: return Message.Create(Database, flags, RedisCommand.SET, key, value, RedisLiterals.XX);

                }

            }

我们通过程序并行测试调用执行 2000 次 SETNX 命令,分 2 次执行,其中 key 的缓存有效期为 5 秒,也就是 5 秒后会自动释放 key,也就是释放锁。

代码如下:

using StackExchange.Redis;

using System;

using System.Diagnostics;

using System.Threading;

using System.Threading.Tasks;

namespace ConsoleApp1

{

    class Program

    {

        private static int safeInstanceSuccessedCount = 0;

        private static int safeInstanceFailedCount = 0;

        private readonly static ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(“127.0.0.1:8899,password=123”);

        private readonly static IDatabase database = redis.GetDatabase(0);

        static void Main(string[] args)

        {

            Stopwatch watch = new Stopwatch();

            watch.Start();

            Parallel.For(0, 1000, (i) => {

                SetNX(“ITEM:1”, “itsvse.com”);

            });

            watch.Stop();

            Console.WriteLine(“用时{0}毫秒”, watch.ElapsedMilliseconds);

            Console.WriteLine(“Successed:”+ safeInstanceSuccessedCount);

            Console.WriteLine(“Failed:” + safeInstanceFailedCount);

            Thread.Sleep(6000); //key值缓存5秒时间,阻塞6秒

            watch.Restart();

            Parallel.For(0, 1000, (i) => {

                SetNX(“ITEM:1”, “itsvse.com”);

            });

            watch.Stop();

            Console.WriteLine(“用时{0}毫秒”, watch.ElapsedMilliseconds);

            Console.WriteLine(“Successed:” + safeInstanceSuccessedCount);

            Console.WriteLine(“Failed:” + safeInstanceFailedCount);

            Console.WriteLine(“by:itsvse.com”);

        }

        static void SetNX(string key,string value)

        {

            var ret = database.StringSet(key, value, TimeSpan.FromSeconds(5), When.NotExists, CommandFlags.None);

            if(ret)

                Interlocked.Increment(ref safeInstanceSuccessedCount);

            else

                Interlocked.Increment(ref safeInstanceFailedCount);

        }

    }

}

可以看到,一共成功插入插入 2 次,失败了 1998 次,完全符合我们的预期,效果图如下:
.NET Core 基于 Redis 实现分布式锁原理解析

这时候,还没有去释放锁。


更多技术请关注

.NET Core 基于 Redis 实现分布式锁原理解析


.NET Core 基于 Redis 实现分布式锁原理解析》来自互联网,仅为收藏学习,如侵权请联系删除。本文URL:https://www.hashtobe.com/599.html