库存超卖—解决方案1 乐观锁
使用乐观锁解决秒杀系统原理(仅限数据量小的库存)1. 业务流程:(1)库存>0就减库存,并记录减了库存的用户到抢购成功记录表中,(2)前台调用接口查询是否抢购成功。2. 采用乐观锁防止库存<0乐观锁就是认为不会产生数据访问冲突。比如update修改商品status为2update 表 set status=2, version=version+1where id=#{id} and v
文章参考秒杀java代码(乐观锁、行锁防止库存超卖) - 简单版本v1_祁_z-CSDN博客
使用乐观锁解决库存超卖(仅限数据量小的库存)
1. 业务流程:
(1)库存>0就减库存,并记录减了库存的用户到抢购成功记录表中,
(2)前台调用接口查询是否抢购成功。
2. 采用乐观锁防止库存<0
乐观锁就是认为不会产生数据访问冲突。比如update修改商品status为2
update 表 set status=2, version=version+1
where id=#{id} and version=#{version};
3.原理分析
乐观锁:如果有100库存,同时来一百线程,有的线程会查询到相同的版本号,所以不会一次减完100个库存。
因此使用乐观锁的步骤为:
(1) 第一步需要在库存表里添加version版本号字段
(2)根据库存id获取版本值,version返回4
SELECT b.version FROM inventory b WHERE b.inventoryId = #{库存Id}
(3)版本值作为条件进行乐观锁(无锁)进行update
UPDATE inventory SET quantity = quantity - 1, version = a.version + 1 WHERE inventoryId = #{库存Id} AND quantity > 0 AND a.version = 4
4. 具体代码
public interface TestMapper {
// 乐观锁减库存
@Update("UPDATE inventory SET quantity = quantity - 1, version = version + 1 WHERE inventoryId = #{inventoryId} AND quantity > 0 AND version = #{version}")
int subtractInventoryOptimisticByVersion(@Param("inventoryId")int inventoryId, @Param("version")Integer version);
// 查询商品库存是否存在,返回版本号
@Select("select version from inventory where inventoryId = #{inventoryId} limit 1")
Integer getInventory(@Param("inventoryId")Integer inventoryId);
}
5. 总结
减库存乐观锁、行锁总结
// 如果采用提前生成库存数量保存到redis后,就没必要使用乐观锁了,直接使用行锁机制就行
因为:能在redis抢到令牌的,就已经代表抢到了商品,所以使用乐观锁和行锁是没什么区别的
// 乐观锁:如果有100库存,同时来一百线程,有的线程会查询到相同的版本号,所以不会一次减完100个库存。
// 行锁:两个线程操作同一行数据,由于InnoDB为行锁,在A会话未提交时,B会话只有阻塞等待。如果操作不同行,则不会出 -现阻塞情况。防止了数据一致性的问题
更多推荐
所有评论(0)