.net 6 基于Redis的单机分布式锁

控制台例子:

1. Nuget包管理器添加 StackExchange.Redis 

2.代码如下:

using StackExchange.Redis;


ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost,password=123456");
IDatabase db = redis.GetDatabase();

//redis键名
string resource = "myResourceName";

//锁的令牌
string lockToken = Guid.NewGuid().ToString();

//过期时间
TimeSpan expiry = TimeSpan.FromSeconds(5);

var tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
    int client = (i + 1);
    tasks[i] = Task.Run(async () =>
    {
        while (true)
        {
            //获得锁
            if (db.LockTake(resource, lockToken, expiry))
            {
                Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} ********************************* 客户端{client} 创建了锁 ********************************* ");

                //开启异步线程,定时2秒延长锁
                var cancellationTokenSource = new CancellationTokenSource();
                var extendLockTask = Task.Run(async () =>
                {
                    while (true)
                    {
                        await Task.Delay(TimeSpan.FromSeconds(2), cancellationTokenSource.Token);
                        bool extended = db.LockExtend(resource, lockToken, expiry);
                        if (extended)
                        {
                            Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} --------------- 客户端{client} 已延长了锁 ---------------");
                        }
                        else
                        {
                            Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}--------------- 客户端{client} 延长了锁失败!---------------");
                            break;
                        }
                    }
                }, cancellationTokenSource.Token);

                //模拟任务耗时
                await Task.Delay(60);

                //取消延长
                cancellationTokenSource.Cancel();
                try
                {
                    await extendLockTask;
                }
                catch (OperationCanceledException)
                {
                    //Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}--------------- 客户端{client} 延长任务取消!---------------");
                }

                //释放锁
                db.LockRelease(resource, lockToken);

                Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} ********************************* 客户端{client} 释放了锁 ********************************* ");
                break;
            }
            else
            {
                //获取锁失败以后重试
                //Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} 客户端{client}获取锁失败,正在重试...");
                //await Task.Delay(50);
            }
        }
    });
}

Task.WaitAll(tasks);


Task.WaitAll(tasks);
Console.WriteLine("按下回车键停止...");
Console.ReadLine();