分布式锁之-mysql

发布于:2024-05-11 ⋅ 阅读:(115) ⋅ 点赞:(0)

使用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 若需完整代码 可识别二维码后 给您发代码。
若友友们有更好的分布式锁的实现方式 请在评论区留下你可贵的分享 谢谢!!!!
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到