商品订单库存一致性问题的思考

摘要:
(关于库存锁定流程有一个小细节,请参见附录1)两种方案的比较方案11)如果100人同时下单,秒杀场景可以确保付款时所有产品都售出。商品订单库存业务的实现方法和优化不仅具有用户下单的功能,还为商家提供了在管理后台修改库存的权限。用户操作和管理员后台操作都放在清单中。要修改库存,管理员必须从全局库存锁中获取锁。一旦管理后台修改了库存锁,用户还必须在下订单后操作数据库来修改库存。

首先先确认方案

方案1:下单后减库存;用户下单,然后库存加锁,判断库存是否充足,用户下单完成,减库存,最后释放库存锁。

方案2:支付才减库存;用户支付,然后库存加锁,判断库存是否充足,用户支付完成,减库存,最后释放库存锁。

当然还有其他方案,这里只阐述我的思考。

(库存加锁的过程有个小细节请看附1

种方案的比较

方案1

1)假如100个人同时下单,只有一个人能下单成功。

2)此时订单应该有一个过期状态,如果订单过期,库存加锁并回写库存后释放锁。

方案2

1)100个人可以同时下单,但是100个人同时付款时,只有一个人付款成功。

正常情况下,商品加入购物车的用户>>>下单的用户>=付款的用户。如果从库存加锁的角度来说,在下单的时候加锁,那么高并发下用户体验可能比较差,因为同时下单只有一个人能下单成功,而且服务器性能可能会比较差;下单的请求变多,那么请求加锁的次数也变多了,而支付的用户可能小于下单的用户,请求加锁的次数理论上会少不少。

我的建议是:

普通的电商项目我认为方案一就足够了,因为下单的流程简单,而支付可能涉及到很多业务,如果支付里面锁库存,考虑的东西会有点多。

但是在高并发下或者秒杀场景下,那可能就要在支付的时候锁库存。从业务角度来说,肯定是手快有,手快无;从代码的角度来说,支付跟减库存高度耦合,出现超卖、库存不一致情况大大降低,如果是下单锁库存,万一用户取消订单,那是不是库存要加回去,这种情况下高并发出现库存与实际消费不一致的可能性比较大。而且还有一个好处,秒杀场景在支付时候加锁能够保证所有的产品都卖出去,而在下单的时候加锁,那么有可能有用户取消订单,到秒杀结束时有产品没卖出去,如果是老板肯定是要全部卖出去的。

 

实现方式以及优化

商品订单库存这个业务不仅仅只有用户下单这个功能,还要在管理后台提供商家修改库存的入口。那么这样就有两处需要用到库存,必须要考虑竞争问题。

单体架构的实现

单体架构实现这个业务是最简单的,但是性能也是最差的。

商品订单库存一致性问题的思考第1张

单体架构中,不管是用户操作还是管理员后台操作库存都放在里面,然后部署到机器上。此时库存锁是个全局锁,用户下单,管理员要修改库存都要从全局的库存锁拿到锁,执行完业务代码再释放。

这种单体架构就会出现一个问题,耦合度太高,一旦管理后台修改库存占用库存锁,那么用户就不能下单购买商品了。如果是购买量不多的业务,单体架构是可以满足基本需求的,这种实现成本低,易维护但不能支撑高并发。

像大部分中小型公司,一天的订单我感觉也就1000以内,单体架构完全够用了,并不需要改造成下面的方案,增加幂级的复杂度

 

优化方案

如果说业务增长块订单量增大,那么上面的单体架构就有局限性了。特别是现在互联网公司的架构大部分都是微服务分布式。

1)首先,每次加锁后,都需要从数据库查询库存,判断库存,然后用户下完单也要操作数据库修改库存。数据库的操作是需要时间成本的,大流量下如果其中一个用户下单时间太慢,其他用户都要等待他处理完,用户体验太差

2)其次现在架构大部分是分布式、微服务的,用户下单减库存和管理后台修改库存一般都是拆分为两个服务--下单服务和库存服务

 

优化的第一步。要解决下单因为操作数据库耗时过长的问题,我们可以把库存放到缓存中(一般是redis),然后对redis中的库存加redis锁,执行下单,对redis中的库存进行减库存。这么做的好处是提升了用户下单的速率,加大了并发量;其次用户下单跟管理后台的业务解耦了,为以后拆分服务做扩展。如下图:

商品订单库存一致性问题的思考第2张

虽然提升了性能,但是新问题出现了,数据一致性问题。现在业务是独立分开了,用户下单,redis加锁,操作redis的库存就可以了,同样管理后台修改库存,加锁操作数据库的库存就可以了。但是怎么保证这两个地方的库存一致性呢?

 

使用消息队列让数据库的库存进行减库存

用户下单成功后向消息队列发送一条消息,然后在管理后台业务中消费消息,进行减库存,如图:

商品订单库存一致性问题的思考第3张

如果保证了消息的可靠性传输,那么即可保证用户下单后的库存与数据库的库存达到最终一致性。

 

停售同步库存

如果管理后台要修改库存并且同步到redis上去要怎么办?可行的方案是让商家停止出售商品,然后判断redis的库存跟数据库的库存是否一致,若一致,那么商家即可修改库存,修改后更新数据库库存和redis库存。如果不一致,那么你就要知道是否管理后台还没消费完消息队列,还是其他问题,没消费完让商家等一段时间就行了,是其他问题的话程序员就妥妥的背锅吧,必须从日志系统里面查查具体是哪里出问题。

商品订单库存一致性问题的思考第4张

微服务分布式

其实就是把单体架构拆分,具体解决思路不变。具体要看业务把,如果订单不多的话,没必要拆分为订单服务和库存服务或者把他们解耦出来,一开始的单体架构就够用了。至于优化的方案,我感觉独角兽或者大型公司才会用到。也可能我技术角度或者业务角度没达到那种高度。

 

其他问题

因为之前面试,经常就问到商品库存这个问题,现在只是写个自己的思考,肯定有错误的地方。还有很多问题就不去考虑了,毕竟我没做过这个业务,例如生产上因为用户点击过快、网络问题导致的订单重复提交。

 

题外话

算是给点建议吧,一开始找工作尽量找稳定的公司,然后干几年积累技术。我面试的时候因为简历是3年换了3家公司,每次面试都要问我为啥经常离职。而且大公司简历几乎就进不了面试,中小型公司技术面过了,但是HR面因为这个问题也可能会把你刷了。还有就是要从业务上考虑,业务才能驱动技术的提升。(PS:广州真的是一线城市么?工资是真的低,干IT别来广州,别来广州,别来)

 

附1:

高并发或者秒杀场景下,不管是方案1还是方案2,如果库存为0时,是否还是每次都锁库存去走一遍流程,即库存加锁,判断库存是否充足,用户下单完成,减库存,最后释放库存锁,答案肯定是否的。

想一想java实现单例模式的代码,用了两个判断语句,那么这个场景我们也可以使用这种方式。外面先去查询一次库存,再判断是否为0,如果为0直接返回,如果不为0 ,那么库存加锁,判断库存是否充足,用户下单(或支付)完成,减库存,最后释放库存锁。以下单锁库存为例:

商品订单库存一致性问题的思考第5张

商品订单库存一致性问题的思考第6张

免责声明:文章转载自《商品订单库存一致性问题的思考》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇一周信创舆情观察(6.22~6.28)SQL Server 2008禁止修改表结构的解决办法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

VUE三 vue-router(路由)详解

前端路由 根据不同的 url 地址展示不同的内容或页面,无需依赖服务器根据不同URL进行页面展示操作 优点 用户体验好,不需要每次都从服务器全部获取,快速展现给用户 缺点 使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存 单页面无法记住之前滚动的位置,无法在前进,后退的时候记住滚动的位置 一、路由(以user为例) userList--...

Apache用户认证方法汇总(转载)

简介:这是Apache用户认证方法汇总(转载)的详细页面,介绍了和php,有关的知识、技巧、经验,和一些php源码等。 frameborder='0' src='http://biancheng.dnbcw.info/pingjia.php?id=322022' scrolling='no'> Apache用户认证方法汇总 一.基本的Apac...

oracle中监听程序当前无法识别连接描述符中请求服务 的解决方法

原因如下: 你oracle安装成功后,一直未停止数据库(即数据库是启动的),客户端配置成功后,应该一直不会有什么问题。 而一旦你和我同事一样,有时把Oracle安装在虚拟机中,而且Oracle安装完毕后,没在进行任何监听的配置,则虚拟机再启动,则就会出现ORA-12514的问题。如下图       如下是解决思路: 根据出错信息判断出客户端未监听...

2020第44周Windows文件系统不区分大小写

由于Windows文件系统不区分大小写,所以你不能通过大小写来区分文件名或文件夹名,比如你在资源管理器中新建一个A.txt文件,想再建个a.txt时会提示你重名并自动重命名。这在Git操作时可能会遇到问题,比如你代码库里文件或文件夹修改了名称,默认Git认为是没变的,如果单纯让Git在仓库中区分大小写会产生两份文件并且无法在Windows系统中观察到),...

AirtestIDE连接安卓真机及常见问题

上期回顾:AirtestIDE基本功能(二) 以下基于 python3.7;airtest1.1.8;pocoui1.0.81;airtestIDE1.2.8 USB连接 用airtestIDE连接安卓真机之前,得先确保你用PC安装apk没问题。 1. 插上手机,使PC可以识别出手机,一般情况下插上会自动识别,不能识别的自己去手机官网安装驱动。 2....

阿里OneData构建数据指标体系

数据指标来辅助业务决策 GMV、日活用户、月活用户、PV、UV、页面停留时长 OneData指标规范 以维度建模作为理论基础,构建总线矩阵,定义业务域、数据域、业务过程、度量/原子指标、维度、维度属性、修饰词、修饰类型、时间周期、派生指标等。 业务域:比数据域更高维度的业务划分方法,适用于特别庞大的业务系统,且业务板块之间的指标或业务重叠性较小。例如...