分布式锁解决方案_基于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记性测试

把数据库所有数据复原

测试略过

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/20751.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

element-plus 问题

对话框内部下拉框会在左上角 在对话框内打开下拉框后点击关闭按钮&#xff0c;尚未关闭的下拉框会在左上角出现&#xff08;或闪现&#xff09; 解决方案&#xff1a; popper-append-to-body 此方法失效&#xff0c;改用 :teleported"false" teleported&#xff1a;…

思维中的世界

⾝体的空间&#xff0c;以⾏为为导向的空间 感官⼩矮⼈ 当我们观察特定的事物时&#xff0c;⼤脑的相应区域就会被“点亮”&#xff0c;并变得 活跃起来。 ⾝体映射到⼤脑上&#xff0c;映射到“感官⼩矮⼈”上&#xff0c; 即从左⽿延伸&#xff0c;过⼤脑顶⾻&#xff0c;…

心法利器[84] | 最近面试小结

心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会&#xff0c;与大家一起成长。具体介绍&#xff1a;仓颉专项&#xff1a;飞机大炮我都会&#xff0c;利器心法我还有。 2022年新一版的文章合集已经发布&#xff0c;累计已经60w字了&#xff0c;获取方式看这里&…

RT-Thread 2. GD32在 RT-Thread Nano上添加控制台与 FinSH

本篇文档分为两部分&#xff1a; 第一部分是添加 UART 控制台&#xff08;实现打印&#xff09;&#xff1a;用来向控制台对接的终端输出打印信息&#xff1b;该部分只需要实现两个函数&#xff0c;串口初始化和系统输出函数&#xff0c;即可完成 UART 控制台打印功能。 第二部…

全景 I 0基础学习VR全景制作,第26章热点功能-文档

本期为大家带来蛙色VR平台&#xff0c;热点功能—文档功能操作。 功能位置示意 热点&#xff0c;指在全景作品中添加各种类型图标的按钮&#xff0c;引导用户通过按钮产生更多的交互&#xff0c;增加用户的多元化体验。 文档热点&#xff0c;即点击热点后会嵌入式弹出所选文档…

基于Java+SpringMVC+vue+element实现前后端分离校园失物招领系统详细设计

基于JavaSpringMVCvueelement实现前后端分离校园失物招领系统详细设计 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获…

WPF MaterialDesign 初学项目实战(3)动态侧边栏

其他文章 WPF MaterialDesign 初学项目实战&#xff08;0&#xff09;:github 项目Demo运行 WPF MaterialDesign 初学项目实战&#xff08;1&#xff09;首页搭建 WPF MaterialDesign 初学项目实战&#xff08;2&#xff09;首页导航栏样式 创建侧边栏实体类 新建MenuBar文件…

基于MWORKS的电动汽车电平衡分析

1 引言 随着电动汽车的快速发展、电池技术的进步和智能电力管理系统的应用&#xff0c;电动汽车电平衡已经成为了电动汽车技术研究中的重要问题之一。 电动汽车电平衡是指车辆发电机、蓄电池、整车用电器在一定时间内的电能供给与消耗达到平衡状态。如果车辆电能产生与消耗无法…

国产游戏引擎,竟然用来搞民航

​本文源自量子位 | 公众号 QbitAI 只是给飞行员做个“装备”&#xff0c;竟然突破了国内民用航空领域的一大技术难题&#xff1f;&#xff01; 这是一群游戏技术开发者的真实经历。 他们用自研游戏引擎开发了一个飞行模拟软件&#xff0c;能够第一视角模拟飞行员起飞、着陆…

mysql 分组语句测试

建表 建表语句&#xff1a; CREATE TABLE student( id int not null, name char(12), sex char(1) ); 预置数据 insert into student values(1, wh, 1); insert into student values(2, wh1, 0); insert into student values(3, zyx, 0); commit; 增加字段 alt…

Linux -- 进程信号

文章目录 1. 信号量1.1 进程互斥概念1.2 认识信号量 2. 信号入门2.1 信号概念2.2 见一见2.3 signal()系统调用2.4 宏定义信号 3. 信号产生方式3.1 键盘产生信号3.2 系统调用产生信号3.3 软件条件产生信号3.4 硬件异常产生信号3.5 Core dump 4. 阻塞信号4.1 相关概念4.2 信号在内…

1066 Root of AVL Tree(51行代码+超详细注释)

分数 25 全屏浏览题目 切换布局 作者 CHEN, Yue 单位 浙江大学 An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebala…

马斯克们叫停 GPT-5,更像是场行为艺术

目录 01 联名信说了什么&#xff1f; 02 发起方是谁&#xff1f; 03 谁签署了联名信&#xff1f; 04 联名信有哪些问题&#xff1f;三巨头的另外两位 Sam Altman 的表态 其他值得关注的署名者 比如马斯克。 另一个位于前列的署名者是 Stability AI 的创始人 Emad Most…

MySQL---存储函数、触发器

1. 存储函数 MySQL存储函数&#xff08;自定义函数&#xff09;&#xff0c;函数一般用于计算和返回一个值&#xff0c;可以将经常需要使用的计算 或功能写成一个函数。 存储函数和存储过程一样&#xff0c;都是在数据库中定义一些 SQL 语句的集合。 存储函数与存储过程的区…

初识kubernetes

初识kubernetes 1.应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个时代&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其它技术的参与缺点&#xff1a;不能为应用程…

MySQL基础-事务详解

本文主要介绍MySQL事务 文章目录 前言事务定义事务四大特性&#xff08;ACID&#xff09; 事务操作事务并发问题事务隔离级别 前言 参考链接&#xff1a; 链接1链接2 事务定义 事务是一组操作的集合&#xff0c;他是一个不可分割的工作单位&#xff0c;事务会把所有的操作作…

二叉树总结

文章目录 树需要掌握的基本概念二叉树基本特点满二叉树性质 完全二叉树性质 二叉搜索树&#xff08;二叉排序树&#xff09;Binary Search Tree(BST)性质 平衡二叉树性质 红黑树五大性质 B树 二叉树的存储方式链式存储顺序存储 二叉树的遍历 树需要掌握的基本概念 1、节点、根…

Java版spring cloud 本工程项目管理系统源码-全面的工程项目管理

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 如今建筑行业竞争激烈&#xff0c;内卷严重&#xff0c…

接口自动化测试神器:Python+Requests+Unittest让你的测试用例飞起来

B站首推&#xff01;2023最详细自动化测试合集&#xff0c;小白皆可掌握&#xff0c;让测试变得简单、快捷、可靠 随着互联网的发展&#xff0c;越来越多的应用程序采用了分布式架构&#xff0c;并通过API接口进行数据交换。因此&#xff0c;接口自动化测试已经成为了保证软件质…

【探索SpringCloud】服务发现

前言 今天&#xff0c;我们来聊聊SpringCloud服务发现。主要有如下几个议题&#xff1a; 一、服务发现的概念与方案&#xff1b;二、SpringCloud是如何与各个服务注册厂商进行集成的。 服务发现 在微服务架构中&#xff0c;我们不可避免的需要通过服务间的调用来完成系统功能…