Redis 实现简单的分布式锁

  var tasks = new List<Task>();
            var count = 0;
            for (int i = 0; i < 5; i++)
            {
                tasks.Add(Task.Run(() =>
                {
                    var state = false;
                    var ID = Guid.NewGuid().ToString("N");
                    //申请标志位
                    while (!state && count < 15 * 10)
                    {
                        state = RedisCache.Set(CacheManage.GetServerIDKey(), ID, new TimeSpan(0, 0, 15), When.NotExists);
                        if (state)
                        {
                            log.ExInfo($"{ID}:申请到标志位!");
                            break;
                        }
                        else
                        {
                            log.ExInfo($"{ID}:等待");
                        }
                        Thread.Sleep(1000);
                        count++;
                    }
                    if (state)
                    {
                        Console.WriteLine($"{ID}:处理自己的 事情!");
                        Thread.Sleep(5 * 1000);
                        var id = RedisCache.Get(CacheManage.GetServerIDKey());
                        log.ExInfo($"当前Reids标志位:{id},服务自己的标志位:{ID}");
                        if (id == ID)
                        {
                            RedisCache.Remove(CacheManage.GetServerIDKey());
                            log.ExInfo($"{ID}:移除自己的标志位!");
                        }
                    }
                    else
                    {
                        log.ExError(new Exception($"{ID}:在指定时间未获取到标志位!"));
                    }
                }));
            }
            Task.WaitAll(tasks.ToArray());
            Console.ReadLine();

效果也是很明显哦

 

新增加一个类,方便操作

    /// <summary>
    /// 实现一个redis锁,实现对特定资源的占用
    /// </summary>
    public class RedisLock
    {
        private RedisCache redisCache;
        private string key;
        private string value;
        private TimeSpan TimeSpan;
        private TimeSpan TimeOut;
        public RedisLock(RedisCache redisCache, string key, string value, TimeSpan timeSpan, TimeSpan? timeout = null)
        {
            this.key = key;
            this.value = value;
            this.TimeSpan = timeSpan;
            this.TimeOut = timeout.HasValue ? timeout.Value : timeSpan.Add(new TimeSpan(0, 0, 2));
            this.redisCache = redisCache;
        }
        /// <summary>
        /// 处理动作
        /// </summary>
        public bool Process(Action<bool> action)
        {
            bool state = false;
            try
            {
                state = Lock();
                if (state)
                {
                    action?.Invoke(state);
                }
            }
            finally
            {
                UnLock(state);
            }
            return state;
        }
        /// <summary>
        /// 申请锁
        /// </summary>
        /// <returns></returns>
        private bool Lock()
        {
            DateTime dateTime = DateTime.Now;
            var state = false;
            //申请标志位
            while (!state && (DateTime.Now - dateTime) < TimeOut)
            {
                state = redisCache.Set(key, value, TimeSpan, When.NotExists);
                if (state)
                {
                    break;
                }
                SpinWait.SpinUntil(() => false, 200);
            }
            return state;
        }
        /// <summary>
        /// 释放锁
        /// </summary>
        /// <returns></returns>
        private bool UnLock(bool lockState)
        {
            if (lockState)
            {
                redisCache.Remove(key);
            }
            else
            {
                var data = redisCache.Get(key);
                if (data == value)
                {
                    redisCache.Remove(key);
                }
            }
            return true;
        }
    }
        public static void Test()
        {
            var RedisCache = new RedisCache(ConfigManage.Bind<RedisConfig>("RedisConfig"));
            var log = LogManager.GetLogger("DefaultLog");
            var tasks = new List<Task>();
            for (int i = 0; i < 5; i++)
            {
                tasks.Add(Task.Run(() =>
                {
                    var state = false;
                    var ID = Guid.NewGuid().ToString("N");
                    var redislock = new RedisLock(RedisCache, "key", ID, new TimeSpan(0, 0, 15), new TimeSpan(0, 0, 15 * 10));
                    redislock.Process(()=> {
                        log.ExInfo($"{ID}:申请到标志位!");
                        Console.WriteLine($"{ID}:处理自己的 事情!");
                        Thread.Sleep(5 * 1000);
                    });
                }));
            }
            Task.WaitAll(tasks.ToArray());
            Console.ReadLine();
        }

posted @ 2022-04-25 17:17  蓝创精英团队  阅读(3)  评论(0)    收藏  举报  来源