上一篇文章简单的介绍了单机的情况下如何进行加锁,防止高并发带来的问题。

然而现实中,一般会高并发的应用,很少会单机部署。当用户量达到一定的程度,分布式、集群部署是必然的选择。在分布式部署的情况下,之前的单机锁还会有效吗?代码还是之前的代码:

    private static object lck = new object();
/// <summary>
/// 单机锁
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
[HttpGet]
public int Reduce1()
{
lock(lck)
{
int r = 0;
string key = "stock";
string stock = Rds.cli.Get(key);
r = int.Parse(stock);
if (r > 0)
{
r--;
Rds.cli.Set(key, r);
}
else
{
throw new Exception("库存用尽!");
}
return r;
}
}

今天再来测试一下,首先在本机模拟分布式的部署。

api 部署3个,分别对应的端口 1020、1021、1022。使用nginx进行负载均衡转发,Nginx简单配置信息如下:



Jmeter请求的接口是nginx的8000,请求线程和上一次一样100*10





1000次请求后,再去查库存,发现库存并不为0。所以单机锁,在分布式的情况下,根本没起作用。

所以在分布式的情况下,必须要借助第三方的中间件。Redis是其中比较常见的解决方案,以下是简单的实现代码:

    /// <summary>
/// 分布式锁
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
[HttpGet]
public int Reduce2()
{
bool Lck1 =false;
int r = 0;
string identity=Guid.NewGuid().ToString(); //设置识别,避免错误释放锁。
int OverTime = 10; //根据实际业务场景设置 超时时间,避免出现死锁
try
{
Lck1 = Rds.cli.SetNx("lock", identity, OverTime);
while (!Lck1)
{
Lck1 = Rds.cli.SetNx("lock", identity, OverTime);
}
string key = "stock";
string stock = Rds.cli.Get(key);
r = int.Parse(stock);
if (r > 0)
{
r--;
Rds.cli.Set(key, r);
}
else
{
throw new Exception("库存用尽!");
}
}
catch (Exception ex)
{
throw;
}
finally
{
string id = Rds.cli.Get("lock");
if(id==identity)
{
Rds.cli.Del("lock");
}
}
return r;
}

再次通过Jmeter 请求nginx 的端口。经过改造后的代码方法,在1000次请求后,库存已经为0。说明此次的分布式锁是有效的。

需要注意的是,要避免死锁,所以加锁的时候,要根据业务场景 设置 过期时间。

为了避免释放错误,加锁的时候也要加上身份认证。

好了此次关于锁的分享完毕。

c# .NET 高级编程 高并发必备技巧(二) - 分布式锁的更多相关文章

  1. 高级java高并发,高性能,分布式,高可用,负载均衡,系统架构实战

    java架构师.集群.高可用.高可扩 展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布 式项目实战 视频课程包含: ...

  2. 高并发解决方案之 redis 分布式锁

    背景:秒杀服务中要写一个定时任务:活动到期时给order微服务发送关闭订单的通知.这需要改变数据库表中的数据,而集群中服务是多节点的方式进行部署,会出现并发执行的情况,所以采用的redis的分布式锁的 ...

  3. asp.net core mvc基于Redis实现分布式锁,C# WebApi接口防止高并发重复请求,分布式锁的接口幂等性实现

    使用背景:在使用app或者pc网页时,可能由于网络原因,api接口可能被前端调用一个接口重复2次的情况,但是请求内容是一样的.这样在同一个短暂的时间内,就会有两个相同请求,而程序只希望处理第一个请求, ...

  4. java高级精讲之高并发抢红包~揭开Redis分布式集群与Lua神秘面纱

    java高级精讲之高并发抢红包~揭开Redis分布式集群与Lua神秘面纱 redis数据库 Redis企业集群高级应用精品教程[图灵学院] Redis权威指南 利用redis + lua解决抢红包高并 ...

  5. C#编程高并发的几种处理方法

    并发(英文Concurrency),其实是一个很泛的概念,字面意思就是“同时做多件事”,不过方式有所不同.在.NET的世界里面,处理高并发大致有以下几种方法: 1,异步编程 异步编程就是使用futur ...

  6. Qt高级编程 高清PDF+源|网盘下载地址附提取码|

    书籍作者:Mark Summerfield(马克 . 萨默菲尔德)(英)   书籍译者:闫锋欣内容简介:本书是一本阐述Qt高级编程技术的书籍.本书以工程实践为主旨,是对Qt现有的700多个类和上百万字 ...

  7. JAVA的高并发基础认知 二

    一.JAVA高级并发 1.5JDK之后引入高级并发特性,大多数的特性在java.util.concurrent 包中,是专门用于多线程发编程的,充分利用了现代多处理器和多核心系统的功能以编写大规模并发 ...

  8. 谈论高并发(十二)分析java.util.concurrent.atomic.AtomicStampedReference看看如何解决源代码CAS的ABA问题

    于谈论高并发(十一)几个自旋锁的实现(五岁以下儿童)中使用了java.util.concurrent.atomic.AtomicStampedReference原子变量指向工作队列的队尾,为何使用At ...

  9. Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition

    锁的概念 从jdk发行1.5版本之后,在原来synchronize的基础上,增加了重入锁ReentrantLock. 本文就不介绍synchronize了,有兴趣的同学可以去了解一下,本文重点介绍Re ...

  10. Hibernate解决高并发问题之:悲观锁 VS 乐观锁

    高并发问题是程序设计所必须要解决的问题,解决此类问题最主要的途径就是对对程序进行加锁控制.hibernate对加锁机制同样做出了实现,常用加锁方式为悲观锁和乐观锁.悲观锁指的是对数据被外界(包括本系统 ...

随机推荐

  1. vue全家桶进阶之路10:修饰符

    Vue2 中的修饰符是指在指令后面添加点号(.)和修饰符名称的方式,用于控制指令的行为.修饰符可以分为事件修饰符和属性修饰符两种类型,下面分别介绍它们的作用和使用方法. 事件修饰符 事件修饰符用于控制 ...

  2. 聊聊Seata分布式解决方案AT模式的实现原理

    什么是Seata分布式事务解决方案 Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.为用户提供了AT.TCC.SAGA和XA事务模式,为用户打造一站式的分布式解决 ...

  3. Spectre.Console-处理依赖注入

    引言 之前说的做自动记录 Todo 执行过程中消耗的时间的Todo 项目,由于想持续保持程序执行,就放弃了 Spectre.Console.Cli,后来随着命令越来越多,自己处理觉得很是麻烦,想了想要 ...

  4. vs2022的一些调试技巧——远程调试&线程检查&性能检查

    visual studio一直都是.net/c#开发人员最受欢迎的编译器,除了强大的代码提示和项目模板,还拥有大量的调试工具,这一期我们介绍下code freeze阶段的一些调试技巧.包括测试环境/生 ...

  5. Python生成器深度解析:构建强大的数据处理管道

    前言 生成器是Python的一种核心特性,允许我们在请求新元素时再生成这些元素,而不是在开始时就生成所有元素.它在处理大规模数据集.实现节省内存的算法和构建复杂的迭代器模式等多种情况下都有着广泛的应用 ...

  6. K8S | 核心原理分析

    目录 一.背景 二.持续集成 三.K8S架构 1.核心组件 2.分层结构 3.核心能力 3.1 发现与负载 3.2 调度 3.3 自动伸缩 四.应用案例 1.服务部署 2.交互流程 五.参考源码 整体 ...

  7. 【Python&RS】GDAL对栅格数据重采样/对齐栅格

            GDAL(Geospatial Data Abstraction Library)是一个在X/MIT许可协议下的开源栅格空间数据转换库.它利用抽象数据模型来表达所支持的各种文件格式.它 ...

  8. 沉思篇-剖析Jetpack的LiveData

    上一篇我们讲到了架构组件中的Lifecycle,由于缺少具体的运用,可能缺少直观的感受,今天我们就用Lifecycle实战一回,看看Lifecycle是怎样运用到LiveData中的. LiveDat ...

  9. C++内敛函数,构造函数,析构函数,浅拷贝

    inline //inline函数可以有声明和实现,但是必须在同一文件//inline函数不能分成头文件和实现文件 inline int add(int x, int y){ //一般不要放循环语句 ...

  10. 了解基于模型的元学习:Learning to Learn优化策略和Meta-Learner LSTM

    摘要:本文主要为大家讲解基于模型的元学习中的Learning to Learn优化策略和Meta-Learner LSTM. 本文分享自华为云社区<深度学习应用篇-元学习[16]:基于模型的元学 ...