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,正确,没超卖

  • 相关阅读:
    RecyclerView 源码分析(一) —— 绘制流程解析
    sqlserver outer join
    获取最后一个标签 xpath
    pytesseract
    pytesseract代码优化
    sql server recursion
    sql
    sql server
    mssql乱码问题
    SQL
  • 原文地址:https://www.cnblogs.com/zjtao/p/11451806.html
Copyright © 2011-2022 走看看