RedLock.Net - 基於Redis分布式鎖的開源實現


 工作中,經常會遇到分布式環境中資源訪問沖突問題,比如商城的庫存數量處理,或者某個事件的原子性操作,都需要確保某個時間段內只有一個線程在訪問或處理資源。

因此現在網上也有很多的分布式鎖的解決方案,有數據庫、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的部分源碼:

 

其它就不多說了,如有疑問,歡迎提出。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM