众所周知, 在多线程中,因为共享全局变量,会导致资源修改结果不一致,所以需要加锁来解决这个问题,保证同一时间只有一个线程对资源进行操作

但是在分布式架构中,我们的服务可能会有n个实例,但线程锁只对同一个实例有效,就需要用到分布式锁----redis setnx

原理:

  修改某个资源时, 在redis中设置一个key,value根据实际情况自行决定如何表示

  我们既然要通过检查key是否存在(存在表示有线程在修改资源,资源上锁,其他线程不可同时操作,若key不存在,表示资源未被线程占用,允许线程抢占,然后将通过setnx设置vlaue,表示资源上锁,其他线程不可同时操作)

  图示:

  

分析:

  我们的服务处于一个集群中,如果只是简单的的使用线程锁来解决以上问题,是存在问题的:因为线程是基于进程的,两个web server处于不同的进程空间

  也就是说,user1的请求发往web server1,那只能与web server1的其他请求进行锁的操作,而不能对web server2的请求产生影响

  上面的图中,user1发往web server1的请求负责处理的线程为Thread1,同理负责处理user2发往web server2的请求的线程thread2

  在同一时刻1,两个线程都读取了mysql中residue_ticket的值为100,对应上图 (1)(2), 各自对100进行-1操作,更新到数据库,对应(3)(4)

  我们预期的情况是residue_ticket值被减少了两次,应该为98,但是实际情况下,两个线程都做了100-1=99的操作,并都将mysql中的值改为了99, 的这就会导致最终数据不一致,所以就要用到分布式锁。

为什么用redis?

  因为redis是单线程的,不存在多线程资源竞争,并且它真的很快

为什么用setnx 而不是set?

  setnx表示只有在key不存在时才能设置成功,但是set会在key存在的情况下修改value

利用setnx的特性,我们可以这样这样设计:

  伪代码:

  # 设置redis锁的
  redis key = 'residue_ticket_lock'   # get_ticket是处理购票的逻辑
  def get_ticket():
    time_out = 5 # 为了防止线程过多,当前线程获取不到锁,长时间处于循环中而导致的性能影响,我们设置一个超时时间,如果当前线程在超时时间内还没有抢占到分布式锁,就返回失败的结果
    while True:
       if redis.setnx('residue_ticket_lock','lock',5):
          # 如果setnx返回True, 表示此刻没有其他线程在操作数据库,当前线程可以上锁成功,注意不仅设置了value=lock,还设置了过期时间,这是必要的,为了防止上锁的线程异常崩掉导致不能释放(删除key)而导致其他所有线程永远拿不到操作权
          residue_ticket = mysql.get('residue_ticket') # 从mysql中获取当前剩余票数
          mysql.update('residue_ticket',residue_ticket-1) # 订购成功,将票数-1,更新数据到mysql
          # 删除key,释放锁
          redis.del('residue_ticket')
          return True
       else:
          # 如果setnx返回False,表示有其他线程对在操作,当前线程等待0.01s,并继续循环
          time.sleep(0.01)
          time_out -= 0.01
          continue
    return False

  

  

  

使用redis分布式锁解决并发线程资源共享问题的更多相关文章

  1. 使用Redis分布式锁处理并发,解决超卖问题

    一.使用Apache ab模拟并发压测 1.压测工具介绍 $ ab -n 100 -c 100 http://www.baidu.com/ -n表示发出100个请求,-c模拟100个并发,相当是100 ...

  2. Redis分布式锁解决抢购问题

    转:https://segmentfault.com/a/1190000011421467 废话不多说,首先分享一个业务场景-抢购.一个典型的高并发问题,所需的最关键字段就是库存,在高并发的情况下每次 ...

  3. redis分布式锁解决超卖问题

    redis事务 redis事务介绍:    1. redis事务可以一次执行多个命令,本质是一组命令的集合. 2.一个事务中的所有命令都会序列化,按顺序串行化的执行而不会被其他命令插入 作用:一个队列 ...

  4. 应用Redis分布式锁解决重复通知的问题

    研究背景: 这几天被支付宝充值后通知所产生的重复处理问题搞得焦头烂额, 一周连续发生两次重复充钱的杯具, 发事故邮件发到想吐..为了挽回程序员的尊严, 我用了Redis的锁机制. 事故场景: 支付宝下 ...

  5. 利用redis 分布式锁 解决集群环境下多次定时任务执行

    定时任务: @Scheduled(cron= "0 39 3 * * *") public void getAllUnSignData(){ //检查任务锁,若其它节点的相同定时任 ...

  6. redis分布式锁在springboot中的实现

    理论知识   redis分布式锁的实现方案请参考文章 如何优雅地用redis实现分布式锁 本案例简介   以秒杀活动为例子,在多线程高并发的情况下需要保证秒杀业务的线程安全性,确保秒杀记录与所扣库存数 ...

  7. 用压测模拟并发、并发处理(synchronized,redis分布式锁)

    使用工具:Apache an 测压命令: ab -n 100 -c 100 http://www.baidu.com -n代表模拟100个请求,-c代表模拟100个并发,相当于100个人同时访问 ab ...

  8. springmvc单Redis实例实现分布式锁(解决锁超时问题)

    一.前言 关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完的问题, 这样会导致: A线程超时时间设为10s(为了解决死锁问题 ...

  9. 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁

    首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...

随机推荐

  1. 安装Cloudera Impala

    安装Cloudera Impala Cloudera Impala是Cloudera Enterprise Core的开源扩展,用于快速返回查询结果. Impala作为你环境的插件,与其他组件的安装独 ...

  2. epoll模型的探索与实践

    我们知道nginx的效率非常高,能处理上万级的并发,其之所以高效离不开epoll的支持, epoll是什么呢?,epoll是IO模型中的一种,属于多路复用IO模型; 到这里你应该想到了,select, ...

  3. SecureCRT的安装以及破破解(内含安装包)

    1.百度网盘连接:链接:https://pan.baidu.com/s/13i8sblGthYtj2SbUTrbmsg  提取码:8cw1 2.解压前先关闭电脑防护软件,否则会杀掉破解软件的 3.压缩 ...

  4. c#两种方式调用google地球,调用COM API以及调用GEPLUGIN 与js交互,加载kml文件,dae文件。将二维高德地图覆盖到到三维谷歌地球表面。

    网络上资源很多不全面,自己在开发的时候走了不少弯路,在这里整理了最全面的google全套开发,COM交互,web端交互.封装好了各种模块功能. 直接就可以调用. 第一种方式:调用COMAPI实现调用g ...

  5. Const用法总结(快速区分指针常量与常量指针)

    想当初面试时,面试官问我熟悉C++么?熟悉的话说一下const的用法,然后我就开始凌乱了~ 其实const的用处还真不少,好好捋顺一下会有很大的帮助. 有时候我们希望定义一种常量,它的值不能被修改,这 ...

  6. (Demo分享)利用JavaScript(JS)做一个可输入分钟的倒计时钟功能

    利用JavaScript(JS)实现一个可输入分钟的倒计时钟功能本文章为 Tz张无忌 原创文章,转载请注明来源,谢谢合作! 网络各种利用JavaScript做倒计时的Demo对新手很不友好,这里我亲手 ...

  7. SSM(一)Mybatis基础

    1.持久化与ORM 持久化是数据在内存与硬盘间相互转化的过程 ORM即对象关系映射 程序员使用面向对象的思维方式处理数据,每个对象都是一个pojo.但是保存数据的时候,却以关系型数据库的方式存储.所以 ...

  8. 15 | 过不了的坎:聊聊GUI自动化过程中的测试数据

  9. Delphi7中Unicode,ANSI,UTF编码问题

    注解: ANSI     'American Standard Code for Information Interchange' 美国信息互换标准代码 ANSI的'Ascii'编码 Unicode ...

  10. mac-VBox-Centos6.6安装增强功能

    1. 更新内核 yum update kernel 2.安装依赖包 yum install kernel-headers yum install kernel-devel yum install gc ...