1.同步代码块synchronized ,lock
public synchronized void reduceCouponStock(long couponId ,Integer num) {
//业务逻辑
}
2.分布式锁 zookeeper,redis
3.直接数据库更新扣减
1)update product set stock=stock-1 where id = 1 and stock>0
2)update product set stock=stock-1 where stock=#{原先查询的库存} and id = 1 and stock>0
3)update product set stock=stock-1,versioin = version+1 where id = 1 and stock>0 and version=#{原先查询的版本号}
方案一:id是主键索引的前提下,如果每次只是减少1个库存,则可以采用上面的方式,只做数据安全
校验,可以有效减库存,性能更高,避免大量无用sql,只要有库存就也可以操作成功.
场景:高并发场景下的取号器,优惠券发放扣减库存等
方案二:使用业务自身的条件做为乐观锁,但是存在ABA问题,对比方案三的好处是不用增加version版本字段。如果只是扣减库存且不在意ABA问题时,则可以采用上面的方式,但业务性能相对方案一就差了点,因为库存变动后sql就会无效
方案三:增加版本号主要是为了解决ABA问题,数据读取后,更新前数据被别人篡改过,version只能做递增
场景:商品秒杀、优惠券方法,需要记录库存操作前后的业务