zoukankan      html  css  js  c++  java
  • 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712

    高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    问题描述:某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖

    方案一

    利用数据库锁机制,对记录进行锁定,再进行操作 

    [sql] view plain copy
     
    1. SELECT * from goods where ID =1 for update;  
    2. UPDATE goods set stock = stock - 1;  

    利用排它锁将并行转化为串行操作,但该方案的性能和用户体验较差

    方案二

    利用redis 实现分布式锁,

    使用setnx命令(在key不存在时,创建并设置value 返回1,key存在时,会反回0)来获取锁,在业务逻辑中,我们可以通过这样的方案来操作

    [java] view plain copy
     
    1. Jedis client = jedisPool.getResource();  
    2. while(client.setnx("lock",String.valueOf(System.currentTimeMillis())) == 0){  
    3.     Thread.sleep(10000);  
    4. }  
    5. ...........................  
    6.  style="white-space:pre">   </span>    client.del("lock")  

    方案二进阶

    考虑到死锁问题,即现成A获取锁后,宕机了,导致锁一直无法释放,我们可以通过get命令获取锁的时间戳,通过他进行超时判断,并进行释放

    [java] view plain copy
     
    1. Long TIMEOUT_SECOUND = 120000L;  
    2. Jedis client = jedisPool.getResource();  
    3. while(client.setnx("lock",String.valueOf(System.currentTimeMillis())) == 0){  
    4.     Long lockTime = Long.valueOf(client.get("lock"));  
    5.     if (lockTime!=null && System.currentTimeMillis() > lockTime+TIMEOUT_SECOUND) {  
    6.         client.del("lock");  
    7.        }  
    8.     Thread.sleep(10000);  
    9. }  
    10. ...........................  
    11. ...........................  
    12. client.del("lock")  

    方案二加强

    方案2的算法中,为了确保在非超时情况下,锁只能由有锁的线程进行释放,可以在value的时间戳中,拼上线程特征码

    [java] view plain copy
     
      1. Long TIMEOUT_SECOUND = 120000L;  
      2. String featureCode = "machine01";  
      3. Jedis client = jedisPool.getResource();  
      4. while(client.setnx("lock",featureCode+":"+String.valueOf(System.currentTimeMillis())) == 0){  
      5.     Long lockTime = Long.valueOf(client.get("lock").substring(9));  
      6.     if (lockTime!=null && System.currentTimeMillis() > lockTime+TIMEOUT_SECOUND) {  
      7.         client.del("lock");  
      8.        }  
      9.     Thread.sleep(10000);  
      10. }  
      11. ...........................  
      12. ...........................  
      13. if (featureCode.equals(client.get("lock").substring(0, 8))) {  
      14.     client.del("lock");  
      15.    }  
  • 相关阅读:
    Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
    DHCP "No subnet declaration for xxx (no IPv4 addresses)" 报错
    Centos安装前端开发常用软件
    kubernetes学习笔记之十:RBAC(二)
    k8s学习笔记之StorageClass+NFS
    k8s学习笔记之ConfigMap和Secret
    k8s笔记之chartmuseum搭建
    K8S集群集成harbor(1.9.3)服务并配置HTTPS
    Docker镜像仓库Harbor1.7.0搭建及配置
    Nginx自建SSL证书部署HTTPS网站
  • 原文地址:https://www.cnblogs.com/shihaiming/p/8515258.html
Copyright © 2011-2022 走看看