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);
        }
    }
}

调用示例,简单粗暴

                DistributedLockManager lockManager=new DistributedLockManager();
                TimeSpan expiryTime = new TimeSpan(0,3,0);

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

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

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

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

时间: 2024-10-21 00:42:50

RedLock.Net - 基于Redis分布式锁的开源实现的相关文章

基于redis分布式锁实现“秒杀”

最近在项目中遇到了类似"秒杀"的业务场景,在本篇博客中,我将用一个非常简单的demo,阐述实现所谓"秒杀"的基本思路. 业务场景 所谓秒杀,从业务角度看,是短时间内多个用户"争抢"资源,这里的资源在大部分秒杀场景里是商品:将业务抽象,技术角度看,秒杀就是多个线程对资源进行操作,所以实现秒杀,就必须控制线程对资源的争抢,既要保证高效并发,也要保证操作的正确. 一些可能的实现 刚才提到过,实现秒杀的关键点是控制线程对资源的争抢,根据基本的线程知识,可

Redlock(redis分布式锁)原理分析

Redlock:全名叫做 Redis Distributed Lock;即使用redis实现的分布式锁: 使用场景:多个服务间保证同一时刻同一时间段内同一用户只能有一个请求(防止关键业务出现并发攻击): 官网文档地址如下:https://redis.io/topics/distlock 这个锁的算法实现了多redis实例的情况,相对于单redis节点来说,优点在于 防止了 单节点故障造成整个服务停止运行的情况:并且在多节点中锁的设计,及多节点同时崩溃等各种意外情况有自己独特的设计方法: 此博客或

Redlock:Redis分布式锁最牛逼的实现

普通实现 说道Redis分布式锁大部分人都会想到:setnx+lua,或者知道set key value px milliseconds nx.后一种方式的核心实现命令如下: - 获取锁(unique_value可以是UUID等) SET resource_name unique_value NX PX 30000 - 释放锁(lua脚本中,一定要比较value,防止误解锁) if redis.call("get",KEYS[1]) == ARGV[1] then return red

redis分布式锁RedLock

先聊下redis普通的分布式锁,用 1.单节点.主从/哨兵模式的分布式锁,安全吗? 或许你了解过,通过如下方式加锁: 设置锁时,使用set命令,因为其包含了setnx,expire的功能,起到了原子操作的效果,给key设置随机值,并且只有在key不存在时才设置成功返回True,并且设置key的过期时间(最好用毫秒) 1 SET key_name my_random_value NX PX 30000 # NX 表示if not exist 就设置并返回True,否则不设置并返回False PX

死磕 java同步系列之redis分布式锁进化史

问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 本章我们将介绍如何基于redis实现分布式锁,并把其实现的进化史从头到尾讲明白,以便大家在面试的时候能讲清楚

redis分布式锁深度剖析

转自https://www.jianshu.com/p/d0caf5d99e56 redis分布式锁的实现主要是基于redis的setnx 命令(setnx命令解释见:http://doc.redisfans.com/string/setnx.html),我们来看一下setnx命令的作用: redis-setnx.png 1.redis分布式锁的基本实现 redis加锁命令: SETNX resource_name my_random_value PX 30000 这个命令的作用是在只有这个ke

Redis分布式锁的try-with-resources实现

Redis分布式锁的try-with-resources实现 一.简介 在当今这个时代,单体应用(standalone)已经很少了,java提供的synchronized已经不能满足需求,大家自然 而然的想到了分布式锁.谈到分布式锁,比较流行的方法有3中: 基于数据库实现的 基于redis实现的 基于zookeeper实现的 今天我们重点说一下基于redis的分布式锁,redis分布式锁的实现我们可以参照redis的官方文档. 实现Redis分布式锁的最简单的方法就是在Redis中创建一个key

Redis分布式锁

转自:https://www.cnblogs.com/linjiqin/p/8003838.html 前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介绍Redis分布式锁实现的博客,然而他们的实现却有着各种各样的问题,为了避免误人子弟,本篇博客将详细介绍如何正确地实现Redis分布式锁. 可靠性 首先,为了确保分布式锁可用,我们至少要确保锁的实现

Redis分布式锁的正确实现方式

前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介绍Redis分布式锁实现的博客,然而他们的实现却有着各种各样的问题,为了避免误人子弟,本篇博客将详细介绍如何正确地实现Redis分布式锁. 可靠性 首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件: 互斥性.在任意时刻,只有一个客户端能持有锁. 不会发生死锁.即使有一个客户端在