在.Net中使用RedLock实现分布式锁
⒈简介
RedLock 分布式锁算法由 Redis 的作者提出,大部分语言都有对应的实现,查看,RedLock.net 是 RedLock 分布式锁算法的 .NET 版实现,用来解决分布式下的并发问题。
RedLock 的思想是使用多台 Redis Master ,节点之间完全独立,节点间不需要进行数据同步,因为 Master-Slave 架构一旦 Master 发生故障时数据没有复制到 Slave,被选为 Master 的 Slave 就丢掉了锁,另一个客户端就可以再次拿到锁。
锁通过 setNX(原子操作) 命令设置,在有效时间内当获得锁的数量大于 (n/2+1) 代表成功,失败后需要向所有节点发送释放锁的消息。
获取锁:
SET resource_name my_random_value NX PX 30000
释放锁:
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
⒉使用
1.创建 .NETCore API 项目
2.Nuget 安装 RedLock.net
Install-Package RedLock.net
3.appsettings.json 添加 redis 配置
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"RedisUrls": [
"127.0.0.1:6379",
"192.168.214.128:6379"
]
}
4.添加 ProductService.cs,模拟商品购买
// 有10个商品库存,如果同时启动多个API服务进行测试,这里改成存数据库或其他方式
private static int stockCount = ;
public async Task<bool> BuyAsync()
{
// 模拟执行的逻辑代码花费的时间
await Task.Delay(new Random().Next(, ));
if (stockCount > )
{
stockCount--;
return true;
}
return false;
}
5.修改 Startup.cs ,创建 RedLockFactory
1.定义RedLockFactory属性
private RedLockFactory lockFactory
{
get
{
var redisUrls = Configuration.GetSection("RedisUrls").GetChildren().Select(s => s.Value).ToArray();
if(redisUrls.Length <= )
{
throw new ArgumentException("RedisUrl 不能为空");
}
var endPoints = new List<RedLockEndPoint>();
foreach (var item in redisUrls)
{
var arr = item.Split(":");
endPoints.Add(new DnsEndPoint(arr[], Convert.ToInt32(arr[])));
}
return RedLockFactory.Create(endPoints);
}
}
2.在 ConfigureServices 注入 IDistributedLockFactory:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton(typeof(IDistributedLockFactory), lockFactory);
services.AddScoped(typeof(ProductService));
}
3.修改 Configure,应用程序结束时释放 lockFactory
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseMvc(); lifetime.ApplicationStopping.Register(() =>
{
lockFactory.Dispose();
}); }
6.在 Controller 添加方法 DistributedLockTest
private readonly IDistributedLockFactory _distributedLockFactory;
private readonly ProductService _productService; public HomeController(IDistributedLockFactory distributedLockFactory,
ProductService productService)
{
_distributedLockFactory = distributedLockFactory;
_productService = productService;
} [HttpGet]
public async Task<bool> DistributedLockTest()
{
var productId = "id";
// resource 锁定的对象
// expiryTime 锁定过期时间,锁区域内的逻辑执行如果超过过期时间,锁将被释放
// waitTime 等待时间,相同的 resource 如果当前的锁被其他线程占用,最多等待时间
// retryTime 等待时间内,多久尝试获取一次
using (var redLock = await _distributedLockFactory.CreateLockAsync(productId, TimeSpan.FromSeconds(), TimeSpan.FromSeconds(), TimeSpan.FromMilliseconds()))
{
if (redLock.IsAcquired)
{
var result = await _productService.BuyAsync();
return result;
}
else
{
Console.WriteLine($"获取锁失败:{DateTime.Now}");
}
}
return false;
}
在文章RedLock 实现分布式锁基础之上修改部分代码编写。
在.Net中使用RedLock实现分布式锁的更多相关文章
- Redis中是如何实现分布式锁的?
分布式锁常见的三种实现方式: 数据库乐观锁: 基于Redis的分布式锁: 基于ZooKeeper的分布式锁. 本地面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的. 要点 Red ...
- springboot 中单机 redis 实现分布式锁
在微服务中经常需要使用分布式锁,来执行一些任务.例如定期删除过期数据,在多个服务中只需要一个去执行即可. 以下说明非严格意义的分布式锁,因为 redis 实现严格意义的分布式锁还是比较复杂的,对于日常 ...
- Springboot中使用Redisson实现分布式锁
1. 概述 老话说的好:便宜没好货,有价值的商品,即使再贵,也有人会买. 言归正传,今天继续讨论有关"锁"的话题,synchronized 和 ReentrantLock 大家应该 ...
- Spring Cloud分布式微服务系统中利用redssion实现分布式锁
在非分布式系统中要实现锁的机制很简单,利用java.util.concurrent.locks包下的Lock和关键字synchronized都可以实现.但是在分布式系统中,如何实现各个单独的微服务需要 ...
- RedLock 实现分布式锁
J并发是程序开发中不可避免的问题,根据系统面向用户.功能场景的不同,并发的重视程度会有不同.从程序的角度来说,并发意味着相同的时间点执行了相同的代码,而有些情况是不被允许的,比如:转账.抢购占库存等, ...
- 分布式锁之三:Redlock实现分布式锁
之前写过一篇文章<如何在springcloud分布式系统中实现分布式锁?>,由于自己仅仅是阅读了相关的书籍,和查阅了相关的资料,就认为那样的是可行的.那篇文章实现的大概思路是用setNx命 ...
- 如何用Redlock实现分布式锁
转载请标明出处: http://blog.csdn.net/forezp/article/details/70305336 本文出自方志朋的博客 之前写过一篇文章<如何在springcloud分 ...
- spring-boot 中实现标准 redis 分布式锁
一,前言 redis 现在已经成为系统缓存的必备组件,针对缓存读取更新操作,通常我们希望当缓存过期之后能够只有一个请求去更新缓存,其它请求依然使用旧的数据.这就需要用到锁,因为应用服务多数以集群方式部 ...
- .Net 下基于Redlock redis 分布式锁实现
Redlock-cs (C#/.NET implementation). RedLock.net (C#/.NET implementation). Includes async and lock e ...
随机推荐
- MessagePack Java Jackson 在不关闭输入流(input stream)的情况下反序列化多变量
com.fasterxml.jackson.databind.ObjectMapper 在读取输入流变量的时候默认的将会关闭输入流. 如果你不希望关闭输入流,你可以设置 JsonParser.Feat ...
- 微信小程序_(组件)scroll-view可滚动视图
微信小程序scroll-view组件官方文档 传送门 提前准备:使用<view>组件制作五条撑满的横向区域 <!--index.wxml--> Cynical丶Gary < ...
- python3 格式化输出,字符串操作,模块,列表,元组
初识python,在网上看了老男孩的视频,建立一个博客将自己所学的python知识记录下来. input加密,用于输入密码的阶段. import getpass user = input(" ...
- import 和 require 的 区别
node编程中最重要的思想就是模块化,import和require都是被模块化所使用. 遵循规范 require 是 AMD规范引入方式 import是es6的一个语法标准,如果要兼容浏览器的话必须转 ...
- 最少步数&P1443 马的遍历
1330:[例8.3]最少步数 s数组:记录(1,1)到达每一点需要的最少步数 s[1][1]自然为 0,其余初始化为 -1 que数组:que[#][1] 表示(1,1)可到达点的 x 坐标 q ...
- java高级之Io流
1.1,什么是io流? 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作 ...
- 六十:Flask.Cookie之flask设置cookie的有效域名
设置cookie有效域名cookie默认只能在主域名下使用,如果要在子域名下使用,则应该给set_cookie设置属性domain='.主域名',此时,此cookie在此主域名下的所有子域名均有效 f ...
- mac 安装photoshop + 破解
项目开发中毫无疑问会用到图片,一般情况都是UI将图片切好的,只是,有时候项目中少了一张图片或者是改变图片的尺寸之类的问题,这里我们就不需要每次都找UI要图片了,作为程序员这些基础工具的使用,咱们还是要 ...
- C基础知识(14):命令行参数
命令行参数是使用main()函数参数来处理的,其中,argc是指传入参数的个数,argv[]是一个指针数组,指向传递给程序的每个参数. 应当指出的是,argv[0]存储程序的名称,argv[1]是一个 ...
- Kubernetes中的PV和PVC
K8S引入了一组叫作Persistent Volume Claim(PVC)和Persistent Volume(PV)的API对象,大大降低了用户声明和使用持久化Volume的门槛.在Pod的Vol ...