分布式锁解决方案_基于Redisson实现的分布式锁实现

Redisson介绍: https://github.com/redisson/redisson/wiki

Redisson - 是一个高级的分布式协调Redis客服端,能帮助用户在分布式环境中轻松实现一些Java的对象,Redisson、Jedis、Lettuce是三个不同的操作 Redis 的客户端,Jedis、Lettuce 的 API 更侧重对Reids 数据库的CRUD(增删改查),而Redisson API 侧重于分布式开发。

在pom.xml中加入相关依赖:

<!--redisson-->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.17.2</version>
</dependency>

 编写Redis分布式锁工具类

创建包utils并创建工具类RedissonLockUtils

package com.ss.demo.utils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
 * 分布式所
 */
@Slf4j
@Component
public class RedissonLockUtils {
    @Autowired
    private RedissonClient redissonClient;
    /**
     * 上锁
     * @param lockName
     * @return
     */
    public Boolean lock(String lockName) {
        //判断客户端是否存在
        if(redissonClient == null) {
            log.info("RedissonLock  is null");
            return false;
        }
        try {
            //加锁
            RLock lock = redissonClient.getLock(lockName);
            //过期时间为10秒钟
            //这里无需手动解锁,到10秒钟会自动解锁
            lock.lock(10, TimeUnit.SECONDS);
            return true;
        }catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 解锁
     * @param lockName
     * @return
     */
    public Boolean unLock(String lockName) {
        //判断客户端是否存在
        if(redissonClient == null) {
            log.info("RedissonLock  is null");
            return false;
        }
        try {
            //获得那把锁
            RLock lock = redissonClient.getLock(lockName);
            lock.unlock();    //解锁
            return true;
        }catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

然后修改service的接口ITOrderService

package com.ss.demo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ss.demo.domain.TOrder;

/**
 * <p>
 *  服务类
 * </p>
 */
public interface ITOrderService extends IService<TOrder> {
    /**
     * 创建订单方法
     * @param productId
     * @param count
     * @return
     */
    String createOrder(Integer productId, Integer count);
    /**
     * 使用悲观锁进行实现
     * @param productId
     * @param count
     * @return
     */
    String createOrderPessimisticlock(Integer productId, Integer count);
    /**
     * 乐观锁
     * @param productId
     * @param count
     * @return
     */
    String createOrderOptmisticlock(Integer productId, Integer count);
    /**
     * Redis操作
     * @param productId
     * @param count
     * @return
     */
    String createOrderRedis(Integer productId, Integer count);
    /**
     * Redisson操作
     * @param productId
     * @param count
     * @return
     */
    String createOrderRedisson(Integer productId, Integer count);
}

修改service的实现类TOrderServiceImpl

//引入redisson工具类进行上锁和解锁的操作
@Autowired
private RedissionUtils redissonLockUtils;

/**
 * redisson
 * @param productId
 * @param count
 * @return
 */
@Override
public String createOrderRedisson(Integer productId, Integer count) {
    //加锁操作
    String  key = "lock:";
    Boolean lock = redissonLockUtils.lock(key + productId);  //上锁
    //是否获得了锁
    if(!lock) {   //如果未获得锁
        return "未获得锁";
    }
    try {
        //根据商品id获取商品信息
        Product product = productMapper.selectById(productId);
        if(product == null) {
            throw new RuntimeException("购买商品不存在");
        }
        log.info(Thread.currentThread().getName() +"库存数量" + product.getCount());
        //校验库存
        if(count > product.getCount()) {
            throw new RuntimeException("库存不足");
        }
        //更新库存
        product.setCount(product.getCount() - count);
        //更新操作
        productMapper.updateById(product);
        //创建订单操作
        TOrder order = new TOrder();
        order.setOrderStatus(1);
        order.setReceiverName("张三");
        order.setReceiverMobile("12345678765");
        //设置订单价格【商品单价*商品数量】
        order.setOrderAmount(product.getPrice().multiply(new BigDecimal(count)));
        orderMapper.insert(order);  //插入订单操作
        //创建订单商品表的操作
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(order.getId());     //订单Id
        orderItem.setProduceId(product.getId());  //商品Id
        orderItem.setPurchasePrice(product.getPrice()); //购买价格
        orderItem.setPurchaseNum(count);   //购买数量
        orderItemMapper.insert(orderItem);
        return order.getId();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        redissonLockUtils.unlock(key + productId);
    }
    return "失败";
}

修改controller:TOrderController

package com.ss.demo.controller;
import com.ss.demo.service.ITOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 *  前端控制器
 * </p>
 */
@RestController
@RequestMapping("/order")
public class TOrderController {
    @Autowired
    private ITOrderService orderService;

    @PostMapping("/create")
    public String createOrder(Integer productId, Integer count) {
        //return orderService.createOrder(productId, count);
        //return orderService.createOrderRedis(productId,count);
        return orderService.createOrderRedisson(productId, count);
    }
}

启动服务9091,9090

使用Jmeter记性测试

把数据库所有数据复原

测试略过

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值