当前位置:首页 > 洗衣机 > 文章正文

这个真的厉害高并发场景下的订单和库存处理筹划讲得很具体

编辑:[db:作者] 时间:2024-08-25 02:57:01

下单思路:

下单时天生订单,减库存,同时记录库存流水,在这里须要前辈行库存操作再天生订单数据,这样库存修正成功,相应超时的分外情形也可以通过第四步定时校验库存流水来完成终极同等性。

这个真的厉害高并发场景下的订单和库存处理筹划讲得很具体

支付成功删除库存流水,处理完成删除可以让库存流水数据表数据量少,易于掩护。
未支付取消订单,还库存+删除库存流水定时校验库存流水,结合订单状态进行相应处理,担保终极同等性

(退单有单独的库存流水,申请退单插入流水,退单完成删除流水+还库存)

什么时候进行减库存方案一:加购时减库存。
方案二:确认订单页减库存。
方案三:提交订单时减库存。
方案四:支付时减库存。

剖析:

方案一:在这个韶光内加入购物车并不代表用户一定会购买,如果这个时候处理库存,会导致想购买的用户显示无货。
而不想购买的人一贯占着库存。
显然这种做法是不可取的。
唯品会购物车锁库存,但是他们是另一种做法,加入购物车后会有一定时效,超时会从购物车打消。
方案二:确认订单页用户有购买希望,但是此时没有提交订单,减库存会增加很大的繁芜性,而且确认订单页的功能是让用户确认信息,减库存不合理,希望大家对该方案揭橥一下不雅观点,本人暂时只想到这么多。
方案三:提交订单时减库存。
用户选择提交订单,解释用户有强烈的购买希望。
天生订单会有一个支付时效,例如半个小时。
超过半个小时后,系统自动取消订单,还库存。
方案四:支付时去减库存。
比如:只有100个用户可以支付,900个用户不能支付。
用户体验太差,同时天生了900个无效订单数据。

以是综上所述:选择方案三比较合理。

重复下单问题

用户点击过快,重复提交。
网络延时,用户重复提交。
网络延时高的情形下某些框架自动重试,导致重复要求。
用户恶意行为。
办理办法前端拦截,点击后按钮指挥。
后台:(1)redis 防重复点击,不才单前获取用户token,下单的时候后台系统校验这个 token是否有效,导致的问题是一个用户多个设备不能同时下单。

//key , 等待获取锁的韶光 ,锁的韶光 redis.lock("shop-oms-submit" + token, 1L, 10L);

redis的key用token + 设备编号 一个用户多个设备可以同时下单。

//key , 等待获取锁的韶光 ,锁的韶光 redis.lock("shop-oms-submit" + token + deviceType, 1L, 10L);

(2)防止恶意用户,恶意攻击 : 一分钟调用下单超过50次 ,加入临时黑名单 ,10分钟后才可连续操作,一小时许可一次跨时段弱校验。
利用reids的list构造,过期韶光一小时

/ @param token @return true 可下单 / public boolean judgeUserToken(String token) { //获取用户下单次数 1分钟50次 String blackUser = "shop-oms-submit-black-" + token; if (redis.get(blackUser) != null) { return false; } String keyCount = "shop-oms-submit-count-" + token; Long nowSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")); //每一小时清一次key 过期韶光1小时 Long count = redis.rpush(keyCount, String.valueOf(nowSecond), 60 60); if (count < 50) { return true; } //获取第50次的韶光 List<String> secondString = redis.lrange(keyCount, count - 50, count - 49); Long oldSecond = Long.valueOf(secondString.get(0)); //now > oldSecond + 60 用户可下单 boolean result = nowSecond.compareTo(oldSecond + 60) > 0; if (!result) { //触发限定,加入黑名单,过期韶光10分钟 redis.set(blackUser, String.valueOf(nowSecond), 10 60); } return result; } 如何安全的减库存

多用户抢购时,如何做到并发安全减库存?

方案1: 数据库操作商品库存采取乐不雅观锁防止超卖:

sql:update sku_stock set stock = stock - num where sku_code = '' and stock - num > 0;

剖析:高并发场景下,假设库存只有 1件 ,两个要求同时进来,抢购该商品.数据库层面会限定只有一个用户扣库存成功。
在并发量不是很大的情形下可以这么做。
但是如果是秒杀,抢购,瞬时流量很高的话,压力会都到数据库,可能拖垮数据库。

方案2:利用Redis单线程 逼迫串行处理

/ 缺陷并发不高,同时只能一个用户抢占操作,用户体验不好!
@param orderSkuAo / public boolean subtractStock(OrderSkuAo orderSkuAo) { String lockKey = "shop-product-stock-subtract" + orderSkuAo.getOrderCode(); if(redis.get(lockKey)){ return false; } try { lock.lock(lockKey, 1L, 10L); //处理逻辑 }catch (Exception e){ LogUtil.error("e=",e); }finally { lock.unLock(lockKey); } return true; }

剖析:利用Redis 分布式锁,逼迫掌握同一个商品处理要求串行化,缺陷并发不高 ,处理比较慢,不适宜抢购,高并发场景。
用户体验差,但是减轻了数据库的压力。

方案3 :redis + mq + mysql 担保库存安全,知足高并发处理,但相对繁芜。

/ 扣库存操作,秒杀的处理方案 @param orderCode @param skuCode @param num @return / public boolean subtractStock(String orderCode,String skuCode, Integer num) { String key = "shop-product-stock" + skuCode; Object value = redis.get(key); if (value == null) { //条件 提前将商品库存放入缓存 ,如果缓存不存在,视为没有该商品 return false; } //先检讨 库存是否充足 Integer stock = (Integer) value; if (stock < num) { LogUtil.info("库存不敷"); return false; } //不可在这里直接操作数据库减库存,否则导致数据不屈安 //由于此时可能有其他线程已经将redis的key修正了 //redis 减少库存,然后才能操作数据库 Long newStock = redis.increment(key, -num.longValue()); //库存充足 if (newStock >= 0) { LogUtil.info("成功抢购"); //TODO 真正扣库存操作 可用MQ 进行 redis 和 mysql 的数据同步,减少相应韶光 } else { //库存不敷,须要增加刚刚减去的库存 redis.increment(key, num.longValue()); LogUtil.info("库存不敷,并发"); return false; } return true; }

剖析:利用Redis increment 的原子操作,担保库存安全,利用MQ担保高并发相应韶光。
但是是须要把库存的信息保存到Redis,并担保Redis 和 Mysql 数据同步。
缺陷是redis宕机后不能下单。
increment 是个原子操作。

综上所述:

方案三知足秒杀、高并发抢购等热点商品的处理,真正减扣库存和下单可以异步实行。
在并发情形不高,平常商品或者正常购买流程,可以采取方案一数据库乐不雅观锁的处理,或者对方案三进行重新设计,设计成支持单订单多商品即可,但繁芜性提高,同时redis和mysql数据同等性须要定期检讨。

订单时效问题超过订单有效韶光,订单取消,可利用MQ或其他方案回退库存。

设置定时检讨Spring task 的cron表达式定时任务MQ延时行列步队

订单与库存涉及的几个主要知识

TCC 模型:Try/Confirm/Cancel:不该用强同等性的处理方案,终极同等性即可,下单减库存,成功后天生订单数据,如果此时由于超时导致库存扣成功但是返回失落败,则通过定时任务检讨进行数据规复,如果本条数据实行次数超过某个限定,人工回滚。
还库存也是这样。
幂等性:分布式高并发系统如何担保对外接口的幂等性,记录库存流水是实现库存回滚,支持幂等性的一个办理方案,订单号+skuCode为唯一主键(该表修正频次高,少建索引)乐不雅观锁:where stock + num>0行列步队:实现分布式事务 和 异步处理(提升相应速率)redis:限定要求频次,高并发办理方案,提升相应速率分布式锁:防止重复提交,防止高并发,逼迫串行化分布式事务:终极同等性,同步处理(Dubbo)/异步处理(MQ)修正 + 补偿机制

本站所发布的文字与图片素材为非商业目的改编或整理,版权归原作者所有,如侵权或涉及违法,请联系我们删除,如需转载请保留原文地址:http://www.baanla.com/xyj/89391.html

XML地图 | 自定链接

Copyright 2005-20203 www.baidu.com 版权所有 | 琼ICP备2023011765号-4 | 统计代码

声明:本站所有内容均只可用于学习参考,信息与图片素材来源于互联网,如内容侵权与违规,请与本站联系,将在三个工作日内处理,联系邮箱:123456789@qq.com