高并发下怎样优雅的保证扣减库存数据的正确性

DBC 1.6K 0

第一种

同步代码块synchronized ,lock

public synchronized void reduceCouponStock(long couponId ,Integer num) {
//业务逻辑
}
​
问题:synchronized 作用范围是单个jvm实例, 如果做了集群分布式等,就失效了,且单机JVM加锁后就是串行等待问题

第二种

分布式锁 zookeeper,redis (相关可直接小编网站搜索)
可以解决问题

问题:过于笨重,性能有所下降

温馨提示

以下是数据库操作,比较优雅的解决问题

直接数据库更新扣减
update coupon set stock=stock - #{num} where id = #{couponId} and stock>0
//测试如果num大于已有库存,则会变负数
update coupon set stock=stock - #{num} where id = #{couponId} and (stock - #{num})>=0
或者
update coupon set stock=stock - #{num} where id = #{couponId} and stock >= #{num} 
//修复了负数问题
​
如果扣减最多1个,则直接使用这种就行
update coupon set stock=stock-1 where id = #{couponId} and stock>0 
​
延伸
update coupon set stock=stock-1 where id = #{couponId} and stock = #{oldStock}
问题:扣减库存,如果别人补充库存,就存在ABA问题,看业务是否有这个限制,大课采用上面那种
比如
C线程查出来是10个
A线程扣减1个,剩9个
B线程更新了库存,变回10个
C更新的时候发现还是10个,则更新成功, 所以避免这个问题,要求不管谁修改了库存,一定要加个version递增版本号
​
update coupon set stock=stock-1,version=version+1 where id = #{couponId} and stock>0 and versoin=#{oldVersion}

代码编写

    <update id="reduceStock">
        update coupon set stock=stock-1 where id = #{couponId} and stock>0
    </update>

发表评论 取消回复
表情 图片 链接 代码

分享