javaEE高并发之如何更新库存问题

有三个阶段可更新库存:成功加入购物车;点击去支付,生成订订单;点击支付。

分析

1、加入购物车并不代表用户一定会购买,如果这个时候开始预占库存,会导致想购买的无法加入购物车。而不想购买的人一直占用库存,这样的情况对商家是不利的,显然这种做法是不可取的。

2、商品加入购物车后,选择下单,这个时候去预占库存。用户选择去支付说明了,用户购买欲望是比方案一要强烈的。订单也有一个时效,例如半个小时。超过半个小时后,系统自动取消订单,回退预占库存。这个方案相较于方案一是更合理的。

3、如果付款成功之后再减库存,那么很可能存在用户下单后过了几秒,进行在线支付,结果付款成功了却发现库存已经不足,导致购物失败的情况,这样会严重影响购物体验。同时,还要考虑扣款的回退造成更多复杂性(除非,允许一定超卖,或者库存数量“不计” ,另外倘若是秒杀场景,则依然是无法应付。)

所以综上三种情况比对,方案二生成订单时就更新库存是最合适的。

如何安全更新库存?

安全问题简述:

以商品P举例,其主键为pid,那么就是在下单时,将历史库存S修改为 S -N。具体到SQL里,原始操作大概是这样(以SQL SERVER 举例):

update PT set qty = (S - N) where id = pid ;

这是以前的最原始的操作方式,单粒度的看,也没什么大碍。然而,放在一个并发环境中,则立马暴露出诸多问题

假定在同一时刻,有两个用户提交了订单,一样的操作,一样的商品,一样的数量。那么最终商品P的库存数量应该为 S - N - N。而执行上面的SQL,因为并发,导致两次查询到历史库存均是S(应该至少有一次qty为S - N),则更新完毕后,商品数量最终是 S – N(可以通过线程同步解决该问题,但是这样效率过低)。这种致命性的Bug,也属于超卖(虽然不会扣为负数),如果放在线上,简直是一个定时炸弹。

围绕解决这样的问题,考虑到并发安全以及并发性能,产生了各种解决方案。大体基于两种机制:悲观锁和乐观锁。在诸多场景里,基于每种锁,都有配套的辅助手段。

(1)方案一:使用悲观锁。(适用并发量不大的应用)

仅利用数据库在update时造成的排他锁,使真实更新时串行,并增加库存判断,若库存发生变动,则更新无效,超卖问题也不会发生。譬如(以SQL SERVER 举例):

  update PT set qty = qty - N  where id = pid and qty >= N;(悲观锁)

  严格来讲,这依然是一个较粗的粒度,但不得不说,在单机环境下有一定的可行性。同时,需要考虑高并发情况下(例如商户举办活动,同时参与用户过多)存在一定性能瓶颈,数据库IO负载过大。

(2)方案二:使用乐观锁(不适用并发量较大的商城秒杀活动)

遵循乐观锁的理念,则是默许不会有太大的并发问题(聚焦在小粒度的商品P上,则是认为大多数情况下P不会被同时消费),“放任”线程的执行,不做管控。但是会在关键地方进行版本核对,假如失败,则内部重试或抛出失败信号。

数据库层面上,增加显式的版本号字段(version)。

购买商品P,下单这里需要获取到当前时刻对应的库存qty01,当前记录是版本version01,然后在真实更新时,再次查询商品P的库存,以及对应的当前的版本version02,如果 version01 == version02,那么可以更新。否则,当前数据已因并发被修改,无法更新。这更像是数据库的“不可重复读”,而出现这种情况后(高并发情况下,出现概率直线上升),必须附有关联的内部尝试机制(注意保证幂等性)。 这是一种实现并发管控的方案,但只适合存在并发,但并发量不太大的情况,否则,一是违背乐观锁的理念初衷,二是整体性能以及体验会大打折扣。

具体可查看如下乐观锁相关链接:https://blog.csdn.net/zhangdehua678/article/details/79594212

(3)方案三(综合方案:乐观锁+缓存):

如果秒杀活动,因为商品数量有限,但是人数很多,这个肯定不能直接操作数据库的,会挂的。直接读库写库对数据库压力太大,要用缓存。

即可以将要卖出的商品比如10个商品放到缓存中;然后在redis的memcache里设置一个(k,v)计数器来记录请求数,这个请求书你可以以你要秒杀卖出的商品数为基数,比如你想卖出10个商品,只允许100个请求进来。那当计数器达到100的时候,后面进来的就显示秒杀结束,这样可以减轻你的服务器的压力。然后根据这100个请求,先付款的先得后付款的提示商品以秒杀完。

如下图:

javaEE高并发之如何更新库存问题相关推荐

  1. Java怎么避免重复订单_javaEE高并发之如何产生唯一不重复订单号

    javaEE高并发之如何产生唯一不重复订单号 1.方案一:使用进程ID,线程ID,IP,MAC地址和时间戳进行拼接产生订单号 (1)如果没有并发,订单号只在一个线程内产生,那么由于程序是顺序执行的,不 ...

  2. java 高并发_Java 高并发之无锁(CAS)

    Java 高并发之无锁(CAS) 本篇主要讲 Java中的无锁 CAS ,无锁 顾名思义就是 以不上锁的方式解决并发问题,而不使用synchronized 和 lock 等.. 1. Atomic 包 ...

  3. Java生鲜电商平台-高并发核心技术订单与库存实战

    Java生鲜电商平台-高并发核心技术订单与库存实战 一. 问题 一件商品只有100个库存,现在有1000或者更多的用户来购买,每个用户计划同时购买1个到几个不等商品. 如何保证库存在高并发的场景下是安 ...

  4. 高并发之服务降级和服务熔断____服务降级、熔断、限流的区别

    高并发之服务降级和服务熔断 服务降级: 服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此环节服务器的压力,以保证核心任务的进行. 同时保证部分甚至大部分任务客户能得到正确的 ...

  5. 高并发之并发容器详解

    高并发之并发容器详解 一.vector Vector 是矢量队列,它是JDK1.0版本添加的类.继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口 ...

  6. 高并发之——创建线程池居然有这么多方式...

    来自:冰河技术 前言 在Java的高并发领域,线程池一直是一个绕不开的话题.有些童鞋一直在使用线程池,但是,对于如何创建线程池仅仅停留在使用Executors工具类的方式,那么,创建线程池究竟存在哪几 ...

  7. 【java】高并发之限流 RateLimiter使用

    1.概述 转载原文:高并发之限流 你可能知道高并发系统需要限流这个东西,但具体是限制的什么,该如何去做,还是模凌两可.我们接下来系统性的给它归个小类,希望对你有所帮助. google guava中提供 ...

  8. 随心听出高质量 百度音乐更新支撑电台

    随心听出高质量 百度音乐更新支撑电台  重要在于手機監聽器界面显得过于简约,百度音乐作为播放器来讲功用比拟简易.绝对简易的外表,百度音乐显得很有蕴涵,百度音乐有着壮大的音乐数据作为支撑,不只仅在歌曲数 ...

  9. 高并发之——缓存思路

    缓存特征 (1)命中率:命中数/(命中数+没有命中数) (2)最大元素(空间):代表缓存中可以存放的最大元素的数量,一旦缓存中元素的数量超过这个值,或者缓存数据所占的空间超过了最大支持的空间,将会触发 ...

最新文章

  1. Web前端开发最佳实践(8):还没有给CSS样式排序?其实你可以更专业一些
  2. “领导跳槽想带我走,我要不要跟?”
  3. Linux下自动分割Nginx日志文件(三)-----Logrotate
  4. 【开发环境】PyCharm 打开现有 Python 工程 ( 配置 Python 编译器版本 )
  5. 把CentOS启动进度条替换为详细信息
  6. VTK:几何对象之OpenVRTessellatedBoxSource
  7. python最大正方形的面积_LeetCode 221. 最大正方形 | Python
  8. 云原生大数据架构中实时计算维表和结果表的选型实践
  9. java电脑_电脑上搭建java开发环境
  10. 使用 ADOX 将 Table 添加到 Catalog 时报“类型无效”的原因和解决方法
  11. 现实版“柯南变声领结”!搜狗输入法“变声”功能发布,千人千声一键转换...
  12. 英特尔:5G将释放云的潜力,为垂直行业带来巨大商机
  13. 背景差分检测物体,背景白点去除
  14. “二十一天好习惯”第一期-20
  15. 游戏语音SDK解决回声消除的方案
  16. mysql monitor怎么用,MySQL数据库 监控工具 myMySQL数据库-monitor 详解 MySQL数据库使用教程...
  17. [人脸算法]技术方向综述
  18. CodeForces - 711A 找座位 难度:C++入门 复杂度:简单 翻译难度:难
  19. 详解Wi-Fi连接上网认证接入的原理和过程
  20. InnoDB存储引擎内部结构

热门文章

  1. 02 求解旅行商问题的蚁群算法的python实现
  2. nature news分享的科研神器:ipython notebook
  3. c语言实现按键的抖动与消除,8051单片机实验2——按键识别(一)
  4. 使用GraphInsight打造TuGraph可视化分析应用
  5. Python自动移动电驴下载完成的文件(未完)
  6. 浓情5月感恩母爱:感恩母亲节教育培训主题演讲PPT
  7. 【1093. 大样本统计】
  8. C#开源的信号处理库NWaves
  9. OPPO发布首个自研NPU芯片 马里亚纳 MariSilicon X
  10. 【git】(task1)git基础和常用命令