java 订单减库存_下单减库存

1. 减库存

一般下单减库存的流程大概是这样的:

1、查询商品库存。这里直接查的Redis中的库存。

2、Redis中的库存减1。这里用到的Redis命令是:incrby -1

3、扣减数据库中的库存。这里用数据库乐观锁,不用额外加锁

4、异步刷新Redis中的库存

5、定时扫描超时未支付的交易,库存加回去

总结一下这个流程就是:先减redis库存,再减数据库库存,最后刷新redis库存

用到的Redis命令可能:DECR key  或者  INCRBY key -1

更新数据库的SQL可能是这样的:

update 商品库存表 set 库存 = 库存 - 1 where 商品ID = xxx and 库存 > 0;

或者

update 商品库存表 set 库存 = 库存 - 1 where 商品ID = xxx and version = xxx;

用乐观锁是一种比较好的方式,而且一遍ID字段都有索引,可以充分利用MySQL行级锁

这种方式还有一个比较巧妙的地方是,利用redis的单线程来操作库存,而且又是原子命令,可以避免并发问题

同时,先减redis库存后可以防止后续因库存不足而造成下单失败

最后,数据库更新完以后,再通过MQ异步刷新缓存,可以使得redis中的库存误差不会太大

交易系统会定时扫描超时未支付的订单,然后用MQ异步通知订单和商品中心,将订单关闭,库存再放回去

2. 加锁

加锁(比如:基于Redis的分布式锁)

MQ可以把并行转成串行,但是并不能很好的解决并发访问的问题,只能靠锁

加锁会影响性能,但是影响不大。假设我们用Redisson分布式锁,操作redis只需要几毫秒,因此这点儿损耗不是什么大问题。都是这么玩儿的,不加锁还能怎么办呢。

3. 内存缓存

在cms管理后台修改数据后,同步或异步刷新redis缓存,同时利用zookeeper刷新内存缓存,这样就可以不用等到需要用的时候再从redis中同步。

一定要避免redis大key,最常见的就是hash key,设置的时候不注意,一不小心里面就几千个field了,这对查询非常不利,可以取模进行分片。

一定要避免HGETALL命令,利用Pinpoint可以帮助我们分析每个请求在每个操作所消耗的时候,从而有助于我们优化

数据迁移用Canal

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
订单库存存在超卖问题,通常是由于多线程或分布式环境下对于共享资源的并发访问导致的。在Java中,可以通过以下几种方式来解决订单库存存在超卖问题: 1. 悲观锁:即对于并发访问的共享资源,认为每次访问都会产生冲突,因此在访问共享资源之前先对其进行加锁,阻塞其他的访问请求。在Java中,可以使用synchronized关键字或ReentrantLock类来实现悲观锁。 2. 乐观锁:即对于并发访问的共享资源,认为每次访问都不会产生冲突,因此不对其进行加锁,而是在访问共享资源之前先获取其版本号或时间戳,然后在更新共享资源时进行版本号或时间戳的比较,如果发现冲突,则进行回滚或重试。在Java中,可以使用Atomic类或版本号机制来实现乐观锁。 3. 分布式锁:即对于分布式环境下的共享资源,使用分布式锁来保证其互斥访问。分布式锁可以基于ZooKeeper或Redis等分布式协调服务来实现。 4. 库存预占:即在用户提交订单时,先对订单中所包含的商品进行库存预占,然后在订单支付成功后再进行库存。这种方式可以避免多个用户同时下单导致库存超卖的问题,但需要注意预占的库存要及时释放,否则会导致库存浪费。 以上几种方式都可以用来解决订单库存存在超卖问题,具体选择哪种方式需要根据实际情况进行综合考虑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值