首页 > 编程语言 >c# .NET 高级编程 高并发必备技巧(二) - 分布式锁

c# .NET 高级编程 高并发必备技巧(二) - 分布式锁

时间:2023-08-23 20:11:53浏览次数:41  
标签:cli Rds c# int key NET string 分布式

上一篇文章简单的介绍了单机的情况下如何进行加锁,防止高并发带来的问题。
然而现实中,一般会高并发的应用,很少会单机部署。当用户量达到一定的程度,分布式、集群部署是必然的选择。在分布式部署的情况下,之前的单机锁还会有效吗?代码还是之前的代码:

    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。说明此次的分布式锁是有效的。

需要注意的是,要避免死锁,所以加锁的时候,要根据业务场景 设置 过期时间。
为了避免释放错误,加锁的时候也要加上身份认证。

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

标签:cli,Rds,c#,int,key,NET,string,分布式
From: https://www.cnblogs.com/pzscit/p/17647504.html

相关文章

  • CF1839D
    原题翻译发现我们可以固定里面一段上升子序列不动,我们称这些子序列的点为“选定点”我们不妨能发现答案为非选定点的个数,而放“0球”的个数则为非选定点连续段个数于是我们考虑dp,设\(dp_{i,j}\)表示前\(i\)个数,钦定\(i\)为选定点,前面出了\(j\)个非选定点的连续段容易想到递推......
  • spring web mvc 集成 fastjson2
    maven依赖参考文档https://github.com/alibaba/fastjson2/blob/main/docs/spring_support_cn.md<!-spring5使用这个-><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2-extension-spring5</artifactId&......
  • 随笔(二十九)『docker 3主3从redis配置 』
    1、拉取镜像dockerpullredis:6.0.82、创建并启动容器dockerrun-d--nameredis-node-1--nethost--privileged=true-v/mydata/redis/redis-node-1/data:/dataredis:6.0.8--cluster-enabledyes--appendonlyyes--port6381dockerrun-d--nameredis-node-2--n......
  • org.apache.jasper.servlet.TldScanner$TldScannerCallback.scan(Lorg/apache/tomcat/
    原因<dependency><groupId>org.apache.hive</groupId><artifactId>hive-jdbc</artifactId><version>3.1.3</version></dependency>解决<dependency>......
  • 小白python和pycharm安装大佬勿扰
    编程语言发展和Python安装计算机语言的发展机器语言1946年2月14日,世界上第一台计算机ENIAC诞生,使用的是最原始的穿孔卡片。这种卡片上使用的语言是只有专家才能理解的语言,与人类语言差别极大,这种语言就称为机器语言。机器语言是第一代计算机语言。这种语言本质上是计算机能识......
  • 拨慢人体衰老时钟,MIT 利用 Chemprop 模型发现兼具药效与安全性的细胞抗衰化合物
    内容一览:从光鲜亮丽的明星,到素装淡裹的普通人,大家都会无可避免地老去,经历形容的变化与身体机能的退化。正因为此,人们也在努力寻找延缓衰老的秘方。然而,现有的抗衰老药物总伴有一些副作用。近期,在深度学习的帮助下,《NatureAging》上发表的一篇研究成果筛选出了高效安全的抗衰老药......
  • 史上最强.NET数据分页方法
    【前言】本文讲述的.NET数据分页方法为【史上最强】,已被多家大型科技公司实战采用& 也被圈内多家知名IT培训机构转载收藏。 【正文】支持.NetCore(2.0及以上)与.NetFramework(4.5及以上)可以部署在Docker,Windows,Linux,Mac。数据分页,几乎是任何应用系统的必备功......
  • 4、oracle查看表空间使用情况
    oracle查看表空间使用情况查看表空间大小、使用率、剩余空间selecta.tablespace_name,total,free,total-freeasused,substr(free/total*100,1,5)as"FREE%",substr((total-free)/total*100,1,5)as"USED%"from(selecttablespace_name,sum(bytes)/10......
  • 15、oracle误删数据恢复
    目录oracle误删数据恢复1、delete删除数据2、drop删除表恢复oracle误删数据恢复1、delete删除数据回滚到指定时间点的数据select*fromgscommtypeasoftimestampto_timestamp('2019-08-2823','yyyy-mm-ddhh24');2、drop删除表恢复selectobject_name,origi......
  • IfcAppliedValueSelect
    IfcAppliedValueSelect类型定义IfcAppliedValueSelect定义要在公式中计算的值。类型使用如下:IfcValue:使用项目默认单位的常数值。IfcMeasureWithUnit:使用指定单位的常数值。IfcReference:对象属性上引用的值。对于成本值,以下指南适用:IfcMeasureWithUnit允许指定该值的实际......