• RedLock.Net


     工作中,经常会遇到分布式环境中资源访问冲突问题,比如商城的库存数量处理,或者某个事件的原子性操作,都需要确保某个时间段内只有一个线程在访问或处理资源。

    因此现在网上也有很多的分布式锁的解决方案,有数据库、MemCache、ZoopKeeper等等的方式。

     这次,我们要学习的是一个基于Redis分布式锁的插件,RedLock.Net。

    首先必须要有一个Redis服务来支持此分布式锁,其次就当然是要获取此插件了。

    可以从Nuget中获取,也可以直接去Github下载   https://github.com/samcook/RedLock.net。

     获取到插件,话不多说上代码。这个是分布式锁的封装类,在需要使用锁的地方直接调用即可。

    using RedLock;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    
    namespace KingsBlog.Core
    {
        public class DistributedLockManager
        {
            private List<RedisLockEndPoint> azureEndPoint;
            public DistributedLockManager()
            {
                azureEndPoint = new List<RedisLockEndPoint>();
                azureEndPoint.AddRange(GetEndPoint().Select(o => new RedisLockEndPoint { EndPoint = o.Item1, Password = o.Item2 }));
            }
    
            /// <summary>
            /// 从配置文件获取Redis连接
            /// </summary>
            /// <returns></returns>
            private List<Tuple<EndPoint, string>> GetEndPoint()
            {
                List<Tuple<EndPoint, string>> result = new List<Tuple<EndPoint, string>>();
                var redisParms = RedisCacheBase.ConnectionString.Split(';');
                // "127.0.0.1:6379,password=ucs123;127.0.0.1:6378,password=ucs123;"
                foreach (var re in redisParms)
                {
                    var re1 = re.Split(',');
                    var re2 = re1[0].Split(':');
                    var re3 = re1[0].Split('=');
                    result.Add(new Tuple<EndPoint, string>(new DnsEndPoint(re2[0], Convert.ToInt16(re2.Length > 1 ? re2[1] : "6379")), re3[1]));
                }
                return result;
            }
    
    
            /// <summary>
            /// 阻塞式调用,事情最终会被调用(等待时间内)
            /// </summary>
            /// <param name="resource">锁定资源的标识</param>
            /// <param name="expiryTime">锁过期时间</param>
            /// <param name="waitTime">等待时间</param>
            /// <param name="work"></param>
            public bool BlockingWork(string resource, TimeSpan expiryTime, TimeSpan waitTime, Action work)
            {
                resource = CreateKey(resource);
                using (var redisLockFactory = new RedisLockFactory(azureEndPoint))
                {
                    // blocks until acquired or 'wait' timeout
                    using (var redisLock = redisLockFactory.Create(resource, expiryTime, waitTime, TimeSpan.FromSeconds(1)))
                    {
                        if (redisLock.IsAcquired)
                        {
                            work();
                            return true;
                        }
                    }
                    return false;
                }
            }
            /// <summary>
            /// 跳过式调用,如果事情正在被调用,直接跳过
            /// </summary>
            /// <param name="resource">锁定资源的标识</param>
            /// <param name="expiryTime">锁过期时间</param>
            /// <param name="work"></param>
            public bool OverlappingWork(string resource, TimeSpan expiryTime, Action work)
            {
                resource = CreateKey(resource);
                using (var redisLockFactory = new RedisLockFactory(azureEndPoint))
                {
                    using (var redisLock = redisLockFactory.Create(resource, expiryTime))
                    {
                        if (redisLock.IsAcquired)
                        {
                            work();
                            return true;
                        }
                    }
                    return false;
                }
            }
    
            /// <summary>
            /// 重新设置键
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            private string CreateKey(string key)
            {
                return string.Join("_", RedisCacheBase.SystemCode, "LOCK", key);
            }
        }
    }
    View Code

    调用示例,简单粗暴

                    DistributedLockManager lockManager=new DistributedLockManager();
                    TimeSpan expiryTime = new TimeSpan(0,3,0);
    
                    bool isWork=lockManager.OverlappingWork("LockName",expiryTime,()=>{
                        work(); //Do your job
                    });
                    if(isWork)
                    {
                        //成功执行
                    }
                    else
                    {
                        //未执行
                    }
    View Code

    这样就十分简单地实现了基于Redis的分布式锁。

    代码很简单,有兴趣的朋友也可以利用反编译软件ILSpy去了解RedLock的实现原理,以下两个截图其实就是RedLock的部分源码:

    其它就不多说了,如有疑问,欢迎提出。

  • 相关阅读:
    java的几种对象(PO,VO,DAO,BO,POJO)
    建立标准编码规则(四)-C#编码规范分类及实现
    建立标准编码规则(三)-CodeFixProvider 给代码分析器增加修复建议
    建立标准编码规则(二)-DiagnosticAnalyzer 增加诊断分析代码
    建立标准编码规则(一)-自定义C#代码分析器
    领域模型与微服务
    asp.net core 中使用StyleCop.StyleCopAnalyzers
    asp.net core中使用HttpClient实现Post和Get的同步异步方法
    asp.net core 如何集成kindeditor并实现图片上传功能
    一名前端Web架构师的成长之路(转载)
  • 原文地址:https://www.cnblogs.com/kingsony/p/6513606.html
Copyright © 2020-2023  润新知