zoukankan      html  css  js  c++  java
  • .net Redis分布式锁,Dictionary,ConcurrentDictionary 介绍

    1、背景

    在计算机世界里,对于锁大家并不陌生,在现代所有的语言中几乎都提供了语言级别锁的实现,为什么我们的程序有时候会这么依赖锁呢?这个问题还是要从计算机的发展说起,随着计算机硬件的不断升级,多核cpu,多线程,多通道等技术把计算机的计算速度大幅度提升,原来同一时间只能执行一条cpu指令的时代已经过去。随着多条cpu指令可以并行执行的原因,原来不曾出现的资源竞争随着出现,在程序中的体现就是随处可见的多线程环境。比如要更新数据库的一个信息,如果没有并发控制,多个线程同时操作的话,就会出现互相覆盖的现象发生。

    锁要解决的就是资源竞争的问题,也就是要把执行的指令顺序化。

    在互联网背景下,电商行业是普遍都是多线程执行,并发量大。比如下单秒杀抢购商品活动,属于高并发情况,库存的保证就尤其重要了,不能出现超卖现象。程序员所要做的事情就是需要单线程执行获取库存,再减库存操作,保证数据原子性。

    在多台服务器中,锁就是重点。

    2、应用

    我们先来介绍下单线程下的情况,假设有个商品A,库存500件,假设每次购买1件,单价1元,这样就只有是500次下单时成功的,其他都不能下单。

    2.1  Store商品存储-Dictionary

    数据库不存在的情况下,用Dictionary来代替

     创建了Store后,主程序创建下单,单线程执行。

     执行结果:

     执行正常,4人不能下单。

    改成多线程执行,直接出现超卖现象,其中用Task.Run 模拟多线程,其中Order(int i) i变量注意,不能直接填写i,异步中上下文不存在,因为主线程以及跑完了,再运行异步Task线程,这时变量已是最后一个被覆盖。

    解决方案是重复赋值变量替换

     结果:

     500多的人都买了。

    解决方案:

    2.1.1  lock 加锁

    lock很明显影响性能。

     

     执行结果:

     正常。

    2.1.2  使用ConcurrentDictionary

    ConcurrentDictionary 本身是线程安全的,源代码就是加了lock

     

     

     执行结果符合。

    2.2 用Redis分布式锁

    redis是单线程运行,所以适合。原理也很简单,运用redis以下指令

    1、SETNX
    SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。
    2、expire
    expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。
    3、delete
    delete key:删除key
    在使用Redis实现分布式锁的时候,主要就会使用到这三个命令。

    原理如下:

    1、先获取redis锁,设置一个随机字符串

     

     

     执行了805次,看下输出最后数量有没有小于0

     结果显示0,正确,没超卖

  • 相关阅读:
    mysql常用基本命令
    mysql8.0.13下载与安装图文教程
    k8s ingress 增加跨域配置
    Jenkins 备份恢复插件 thinBackup 使用
    k8s HA master 节点宕机修复
    nginx 跨域问题解决
    mongodb 3.4.24 主从复制
    k8s 线上安装 jenkins并结合 jenkinsfile 实现 helm 自动化部署
    k8s helm 运用与自建helm仓库chartmuseum
    centos6 源码安装 unzip
  • 原文地址:https://www.cnblogs.com/zjtao/p/11451806.html
Copyright © 2011-2022 走看看