使用mysql实现分布式锁的方式这里演示两种:
1:基于 MySQL 实现的乐观锁
2:基于 MySQL 实现的悲观锁
数据库脚本
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for product_stock
-- ----------------------------
DROP TABLE IF EXISTS `product_stock`;
CREATE TABLE `product_stock` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`stock` int(11) NULL DEFAULT 0,
`version` int(11) NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '产品库存表\n' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of product_stock
-- ----------------------------
INSERT INTO `product_stock` VALUES (1, 20,0);
SET FOREIGN_KEY_CHECKS = 1;
使用悲观锁实现
* 模拟减库存操作 - MySQL 悲观锁 实现
*
* @return str
*/
@GetMapping("/reduceStockGloomy/{id}")
public String reduceStockGloomy(@PathVariable("id") Integer id) {
return productStockService.reduceStockGloomy(id);
}
业务实现
/**
* 基于 MySQL 实现分布式锁(悲观锁)
* 悲观锁 :
* 查询的时候,不管有没有线程竞争,都在 MySQL层面就加上了锁 ,
* 所以,整个操作,必须要在一个事务中才行,这里通过 @Transactional
*
* @param id id
* @return String
*/
@Override
@Transactional(rollbackFor = Exception.class)
public String reduceStockGloomy(Integer id) {
// 加锁查询
ProductStock stock = productStockMapper.selectForLock(id);
if (stock != null && stock.getStock() > 0) {
productStockMapper.reduceStock(id);
} else {
throw new RuntimeException("库存不足!");
}
return "ok";
}
乐观锁实现
/**
* 模拟减库存操作 - MySQL 乐观锁 实现
*
* @return str
*/
@GetMapping("/reduceStock/{id}")
public String reduceStockOptimism(@PathVariable("id") Integer id) {
return productStockService.reduceStockOptimism(id);
}
/**
* 乐观锁:
* 我认为我操作之前不会有人操作,如果有人操作了,那我再来一次,即为无锁操作
*
* @param id id
* @return String
*/
@SneakyThrows
@Override
public String reduceStockOptimism(Integer id) {
ProductStock stock = productStockMapper.selectById(id);
if (stock != null && stock.getStock() > 0) {
int i = productStockMapper.reduceStockOptimism(id, stock.getVersion());
// i = 0 表示没有修改成功,说明有别人在你修改之前 已经修改了数据;需要重新再调用下当前方法
if (i == 0) {
// Thread.sleep 防止栈溢出
// Thread.sleep(10);
this.reduceStockOptimism(id);
}
} else {
throw new RuntimeException("库存不足!");
}
return "ok";
}
xml中的版本号的作用
<update id="reduceStockOptimism">
update product_stock
set stock = stock - 1,
version = version + 1
where id = #{id}
and version = #{version}
</update>
以上的是分布式锁之-mysql 若需完整代码 可识别二维码后 给您发代码。
若友友们有更好的分布式锁的实现方式 请在评论区留下你可贵的分享 谢谢!!!!