.Netcore 使用CSRedis Lock分布式加锁原理

news/2024/12/5 2:54:29/

·引用地址:.Netcore 使用CSRedis Lock分布式加锁原理_csredisclientlock_FameLee-的博客-CSDN博客

订阅专栏
1.//使用方法
 
  using (var Lock = RedisHelper.Lock("锁名", "过期时间"))//返回CSRedisClientLock方法
            {
                if (Lock == null)
                {
                    return new Response<bool>().Fail("获取分布式锁失败");
                }
              //业务代码
            }//using结束默认调用CSRedisClientLock的Dispose方法,释放锁
2.//源代码分析
 
    public CSRedisClientLock Lock(string name, int timeoutSeconds, bool autoDelay = true)
        {
            name = $"CSRedisClientLock:{name}";
            var startTime = DateTime.Now;
            while (DateTime.Now.Subtract(startTime).TotalSeconds < timeoutSeconds)//通多过期时间循环去等待加锁
            {
                var value = Guid.NewGuid().ToString();
                if (this.Set(name, value, timeoutSeconds, RedisExistence.Nx) == true)//通过Redis Setnx设置锁也就是redis的 key value
                {
                    double refreshSeconds = (double)timeoutSeconds / 2.0;
                    return new CSRedisClientLock(this, name, value, timeoutSeconds, refreshSeconds, autoDelay);//返回CSRedisClientLock类
                }
                Thread.CurrentThread.Join(3);//加锁失败阻塞当前线程
            }
            return null;
        }
        
    public bool Set(string key, object value, TimeSpan expire, RedisExistence? exists = null)//通过Redis Setnx设置锁成功返回true失败返回false
        {
            object redisValule = this.SerializeRedisValueInternal(value);
            if (expire <= TimeSpan.Zero && exists == null) return ExecuteScalar(key, (c, k) => c.Value.Set(k, redisValule)) == "OK";
            if (expire <= TimeSpan.Zero && exists != null) return ExecuteScalar(key, (c, k) => c.Value.Set(k, redisValule, null, exists)) == "OK";
            if (expire > TimeSpan.Zero && exists == null) return ExecuteScalar(key, (c, k) => c.Value.Set(k, redisValule, expire, null)) == "OK";
            if (expire > TimeSpan.Zero && exists != null) return ExecuteScalar(key, (c, k) => c.Value.Set(k, redisValule, expire, exists)) == "OK";
            return false;
        }
        
    private static RedisStatus.Nullable Set(string key, object value, int? expirationSeconds = null, long? expirationMilliseconds = null, RedisExistence? exists = null)
        {
            var args = new List<object> { key, value };
            if (expirationSeconds != null)
                args.AddRange(new[] { "EX", expirationSeconds.ToString() });
            if (expirationMilliseconds != null)
                args.AddRange(new[] { "PX", expirationMilliseconds.ToString() });
            if (exists != null)
                args.AddRange(new[] { exists.ToString().ToUpperInvariant() });// 通过Setnx设置锁
            return new RedisStatus.Nullable("SET", args.ToArray());
        }
        
public class CSRedisClientLock : IDisposable
    {
 
        CSRedisClient _client;
        string _name;
        string _value;
        int _timeoutSeconds;
        Timer _autoDelayTimer;
 
        public CSRedisClientLock(CSRedisClient rds, string name, string value, int timeoutSeconds, double refreshSeconds, bool autoDelay)
        {
            _client = rds;
            _name = name;
            _value = value;
            _timeoutSeconds = timeoutSeconds;
            if (autoDelay)
            {
                var refreshMilli = (int)(refreshSeconds * 1000);
                var timeoutMilli = timeoutSeconds * 1000;
                _autoDelayTimer = new Timer(state2 => Refresh(timeoutMilli), null, refreshMilli, refreshMilli);
            }
        }
 
 
        /// <summary>
        /// 释放分布式锁
        /// </summary>
        /// <returns>成功/失败</returns>
        public bool Unlock()
        {
            _autoDelayTimer?.Dispose();
            return _client.Eval(@"local gva = redis.call('GET', KEYS[1])
if gva == ARGV[1] then
  redis.call('DEL', KEYS[1])
  return 1
end
return 0", _name, _value)?.ToString() == "1";
        }
 
        public void Dispose() => this.Unlock();
    }
CSRedis GitHub地址

3.分布式加锁流程
1.通过Redis Setnx加锁并设置过期时间。
2.如果锁不存在就加锁。
3.如果锁存在就通过join阻塞线程,循环等待加锁直至过期时间结束。
4.加锁成功后执行业务并释放锁。
5.加锁失败返回错误。
————————————————
版权声明:本文为CSDN博主「FameLee-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40138785/article/details/122124460


http://www.ppmy.cn/news/690716.html

相关文章

随想录(招聘怎样的员工)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 对很多IT公司来说&#xff0c;招聘都是一件大事。无论是校园招聘、社会招聘&#xff0c;公司都会投入到很大的人力和财力来开展招聘工作。一个公司…

网上教学管理系统的设计与实现

网上教学管理系统的设计与实现 第1章 绪 论 1.1 背景 为了促进计算机专业学生工程实践能力的提升&#xff0c;使老师能够更好的管理学生&#xff0c;帮助学生提高学习成绩掌握更多的专业知识&#xff0c;增强师生之间的交流&#xff1b;解决老师教学资料、发布作业、随堂测…

图说区块链:神一样的金融科技与未来社会

内容简介 区块链&#xff0c;如瑞士仪表般精密&#xff0c;如互联网般惊世骇俗&#xff0c;它在以神一般的节奏颠覆社会。 当新兴技术来临时&#xff0c;你可以选择规避——如果明天也可以规避的话。区块链也一样。 作为一个现象级概念&#xff0c;金融科技创新在过去几年迎…

XXX项目总结

一,项目背景 专门给小孩做一个玩手机的模式或者环境&#xff0c;可以看视频&#xff0c;听音乐&#xff0c;电话防乱接&#xff0c;使用时间管控等 二,功能模块 2.1 家长中心 家长中心主要负责&#xff1a;电话监控/时间监控/护眼模式/密码/网络等相关功能 2.1.1 来电监听…

宇宙尽头是铁岭,互联网尽头是贷款

爱因斯坦说&#xff1a;「一个人对社会的价值首先取决于他的感情、思想和行动&#xff0c;对增进人类利益起多大作用。」 而在这个互联网时代&#xff0c;各大 app 对人的价值很可能也有自己的理解 —— 一个人的价值取决于他的消费能力、购买频次、付费意愿&#xff0c;以及他…

网上外卖订餐运营

网上订餐&#xff0c;现在已经有很多家正在经营。较大的有北京的豆丁、上海的129T、深圳的便利中国(已扩展到北京上海)、武汉的美妙食刻等。 较小的地方性的网上订餐&#xff0c;几乎到处都有。详细可看这个帖子提到 http://www.5gme.com/space-111-do-thread-id-1572.html 我…

华为手环8相册表盘使用指南

随着科技的发展&#xff0c;智能手环已经成为越来越多人的选择。华为手环8作为一款备受好评的智能手环&#xff0c;不仅具备精准的监测功能&#xff0c;还拥有丰富的表盘样式。本文将向您介绍华为手环8如何使用相册表盘&#xff0c;通过这一功能&#xff0c;您可以轻松地将您的…

什么是ROM

只读存储器&#xff08;Read-Only Memory&#xff0c;ROM&#xff09;以非破坏性读出方式工作&#xff0c;只能读出无法写入信息。信息一旦写入后就固定下来&#xff0c;即使切断电源&#xff0c;信息也不会丢失&#xff0c;所以又称为固定存储器。ROM所存数据通常是装入整机前…