asp.net mvc asp.net core 基于Redis实现分布式锁 C#

基于Redis实现分布式锁(前提是单台Redis),如果是多台Redis集群,可能有非同步的异常情况。

实现思路:

利用redis的setnx(key, value):“set if not exits”,若该key-value不存在,则成功加入缓存,并且重新设置缓存时间,并且返回1,否则返回0。

这里超过缓存时间,系统会自动释放缓存。

在有效时间内如果设置成功则获取执行限权,没有那就获取权限失败。

下面贴一个示例代码。

新建一个控制台程序,通过NuGet 添加引用 NServiceKit.Redis 。然后把以下代码copy过去。就可以跑示例。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RedisCheckTest
{
    using NServiceKit.Redis;// 通过nuget添加redis库
    class Program
    {

        static void Main(string[] args)
        {
            var m = 0;
            while (m < 1000000)
            {
                m++;
                ///模拟重复发送3次请求
                for (var j = 1; j <= 3; j++)
                {
                    CreateOrderApi(j);
                }
                //for (var i = 1; i <= 3; i++)
                //{//模拟重复发送3次请求
                //    Thread t2 = new Thread(CreateOrderApi);
                //    t2.Start();
                //} 
                Thread.Sleep(8000);
            }
            Console.ReadLine();
        }
        /// <summary>
        /// 比如说这是创建订单方法,
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private static void CreateOrderApi(int request_id)
        {
            string parmaterid = "p2";//假设这是api请求参数id

            var nxkey = "cnx" + parmaterid;
            var value = parmaterid;
            bool setnx = SetNX(nxkey, value);
            if (!setnx)
            {
                Console.WriteLine("requestid: " + request_id.ToString() + " " + "请求太频繁,请10秒后再试。");
                return;
            }
            //todo: 这里写订单逻辑
         
            Console.WriteLine("requestid: " + request_id.ToString() + " " + "Success");
        }


        const string host = "127.0.0.1";
        const int port = 6379;
        public static bool SetNX(string cachekey, string value, int secondsTimeout = 5)
        {
            string NamespacePrefix = "api01_";
            string key = NamespacePrefix + cachekey;
            using (var client = new RedisClient(host, port))
            {
                var byts = System.Text.Encoding.UTF8.GetBytes(value);
                var result = client.SetNX(key, byts);
                var setnx = (result == 1) ? true : false;
                client.Set(key, value, DateTime.Now.AddSeconds(secondsTimeout));//将Key缓存5秒
                return setnx;
            }
        }
        
    }
}

猜你喜欢

转载自www.cnblogs.com/davies/p/11998895.html