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

news/2024/11/16 21:43:48/

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());     //订单IdorderItem.setProduceId(product.getId());  //商品IdorderItem.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记性测试

把数据库所有数据复原

测试略过


http://www.ppmy.cn/news/73419.html

相关文章

Todoist 的 10 种最佳替代品(功能、优点、缺点、定价)

寻找最好的 Todoist 替代品&#xff1f; Todoist对项目管理者来说并不陌生&#xff0c;它自 2007 年以来就一直很出名&#xff01; ……但是作为老牌的组织类应用程序之一&#xff0c;现在再用它是否会觉得有点不顺手&#xff1f; 虽然它为了更好适应当今的工作节奏&#xf…

数据库设计三大范式

数据库设计三大范式 范式就是数据库表设计的依据&#xff0c;教你怎么进行数据库表的设计的。 ● 第一范式&#xff1a;要求任何一张表都必须要有主键&#xff0c;每一个字段原子性不可再分。 ● 第二范式&#xff1a;建立在第一范式的基础之上&#xff0c;要求所有非主键字段完…

在服务器上重新运行flask项目

我昨天运行我的flask项目&#xff0c;因为依赖冲突而重新生成了requirements.txt&#xff0c;现在我需要重新创建虚拟环境吗&#xff1f; 删除了一个依赖&#xff1a;flask_jwt 是的&#xff0c;建议您在生成新的 requirements.txt 文件后重新创建虚拟环境。这样可以确保您的…

2023年NOC大赛创客智慧编程赛项Python 复赛模拟题(二)

题目来自:NOC 大赛创客智慧编程赛项Python 复赛模拟题(二) NOC大赛创客智慧编程赛项Python 复赛模拟题(二) 第一题: 编写一个成绩评价系统,当输入语文、数学和英语三门课程成绩时,输出三门课程总成绩及其等级。 (1)程序提示用户输入三个数字,数字分别表示语文、数学、…

能否在Ubuntu上创造一个虚拟的Ubuntu环境?

可以的。在 Ubuntu 上创建虚拟的 Ubuntu 环境的方式有很多种&#xff0c;常用的有使用 Docker 和虚拟机&#xff08;如 VirtualBox&#xff0c;VMware&#xff09;等。 方法 使用 Docker: Docker 是一种容器技术&#xff0c;它能够让你在隔离的环境中运行应用程序。Docker 可…

Linux Audio (7) DAPM-4 Path/Route添加过程

DAPM-4 Path/Route添加过程 route分类&#xff1a;route转化为Pathcodec驱动add widgetMechine驱动add kcontrol route分类&#xff1a; 常规route {“sink”, NULL, “source”}&#xff0c;其path->connect1 sink widget是Mixer {“Mixer”, name1, “source1”} {“Mixe…

[CISCN 2019华东南]Web4 day5

考察&#xff1a;任意文件读取 获取网卡地址 伪随机 打开界面&#xff0c;点击read somethings直接进行了跳转 直接修改url&#xff0c;发现没显示&#xff0c;但是访问错误的路由就会有no response 读取flag也无果&#xff0c;那就读一下/app/app.py&#xff0c;为什么读这个&…

OpenPCDet系列 | 5.4.1 DenseHead中的AnchorGenerator锚框生成模块

文章目录 AnchorGenerator模块AnchorGenerator.generate_anchors函数 AnchorGenerator模块 首先&#xff0c;根据点云场景将其划分为一个个grid&#xff0c;这个grid size是可以通过配置文件设定的点云场景方位和voxel大小计算出来的。 POINT_CLOUD_RANGE: [0, -39.68, -3, 6…