文章参考秒杀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会话只有阻塞等待。如果操作不同行,则不会出 -现阻塞情况。防止了数据一致性的问题
 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐