【分布式锁】Redission实现分布式锁

接着上一节,我们遇到了超卖的问题,并通过Redis实现分布式锁,进行了解决。本节 我将换一种方式实现分布式锁。

前提:

nginx、redis、nacos

模块1:

provider-and-consumer 端口 8023

模块2

rabbitmq-consumer 端口 8021

添加依赖

xml 复制代码
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.15.6</version>
</dependency>

业务代码

模块1代码 RedisTestController.java

java 复制代码
package com.atguigu.gulimall.providerconsumer.controller;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author: jd
 * @create: 2024-07-08
 */
@RestController
@RequestMapping("/test")
@Slf4j
public class RedisTestController {


    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    @GetMapping("/RedissonLock")
   public String  deductStockByRedisson(){

        //写死一个固定商品ID,作为我们被秒杀的商品
        String lockKey="lock:product:102";
        //获取锁对象
        RLock lock = redissonClient.getLock(lockKey);
        //加锁,使用lock方法,锁将会自动续命
        lock.lock();
        try{
            //获取当前库存
            String stock1 = stringRedisTemplate.opsForValue().get("stock");
            if(stock1==null){
                System.out.println("秒杀未开始,请等开始后操作下单");
                return "end";
            }

            int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
            if(stock>0){
                // 扣减库存
                int realStock = stock - 1;
                // 更新库存
                stringRedisTemplate.opsForValue().set("stock", realStock + "");
                System.out.println("扣减成功,剩余的库存为:" + realStock);
            }else {
                System.out.println("扣减库存失败,库存不足");
            }
        }finally {
            if(lock.isLocked()&&lock.isHeldByCurrentThread()){
                //释放分布式锁
                lock.unlock();
                System.out.println("分布式锁释放"); //解锁
            }
        }

        return "end";
   }



}

模块2代码 RedisTestController.java

java 复制代码
package com.atguigu.gulimall.rabbitmqconsumer.controller;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 *
 * 和provider-and-consumer 这两个服务中都有这个RedisTestController,用来模拟两个不同的服务
 * @author: jd
 * @create: 2024-07-08
 */
@RestController
@RequestMapping("/test")
@Slf4j
public class RedisTestController {


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @GetMapping("/RedissonLock")
    public String  deductStockByRedisson(){

        //写死一个固定商品ID,作为我们被秒杀的商品
        String lockKey="lock:product:102";
        //获取锁对象
        RLock lock = redissonClient.getLock(lockKey);
        //加锁,使用lock方法,锁将会自动续命
        lock.lock();
        try{
            //获取当前库存
            String stock1 = stringRedisTemplate.opsForValue().get("stock");
            if(stock1==null){
                System.out.println("秒杀未开始,请等开始后操作下单");
                return "end";
            }

            int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
            if(stock>0){
                // 扣减库存
                int realStock = stock - 1;
                // 更新库存
                stringRedisTemplate.opsForValue().set("stock", realStock + "");
                System.out.println("扣减成功,剩余的库存为:" + realStock);
            }else {
                System.out.println("扣减库存失败,库存不足");
            }
        }finally {
            if(lock.isLocked()&&lock.isHeldByCurrentThread()){
                //释放分布式锁
                lock.unlock();
                System.out.println("分布式锁释放"); //解锁
            }

        }

        return "end";
    }

}

测试结果:

单次请求,我发送两次,结果:

第二次:

成功扣减。

并发情况模拟:

当前库存数

压测:

并发压测结果:

8023模块

powershell 复制代码
扣减成功,剩余的库存为:83
分布式锁释放
扣减成功,剩余的库存为:81
分布式锁释放
扣减成功,剩余的库存为:80
分布式锁释放
扣减成功,剩余的库存为:78
分布式锁释放
扣减成功,剩余的库存为:76
分布式锁释放
扣减成功,剩余的库存为:75
分布式锁释放
扣减成功,剩余的库存为:72
分布式锁释放
扣减成功,剩余的库存为:68
分布式锁释放
扣减成功,剩余的库存为:66
分布式锁释放
扣减成功,剩余的库存为:64
分布式锁释放
扣减成功,剩余的库存为:62
分布式锁释放
扣减成功,剩余的库存为:60
分布式锁释放
扣减成功,剩余的库存为:58
分布式锁释放
扣减成功,剩余的库存为:56
分布式锁释放
扣减成功,剩余的库存为:54
分布式锁释放
扣减成功,剩余的库存为:52
分布式锁释放
扣减成功,剩余的库存为:50
分布式锁释放
扣减成功,剩余的库存为:48
分布式锁释放
扣减成功,剩余的库存为:46
分布式锁释放
扣减成功,剩余的库存为:44
分布式锁释放
扣减成功,剩余的库存为:42
分布式锁释放
扣减成功,剩余的库存为:40
分布式锁释放
扣减成功,剩余的库存为:38
分布式锁释放
扣减成功,剩余的库存为:36
分布式锁释放
扣减成功,剩余的库存为:34
分布式锁释放
扣减成功,剩余的库存为:32
分布式锁释放
扣减成功,剩余的库存为:30
分布式锁释放
扣减成功,剩余的库存为:28
分布式锁释放
扣减成功,剩余的库存为:26
分布式锁释放
扣减成功,剩余的库存为:24
分布式锁释放
扣减成功,剩余的库存为:22
分布式锁释放
扣减成功,剩余的库存为:20
分布式锁释放
扣减成功,剩余的库存为:18
分布式锁释放
扣减成功,剩余的库存为:16
分布式锁释放
扣减成功,剩余的库存为:14
分布式锁释放
扣减成功,剩余的库存为:12
分布式锁释放
扣减成功,剩余的库存为:10
分布式锁释放
扣减成功,剩余的库存为:8
分布式锁释放
扣减成功,剩余的库存为:6
分布式锁释放
扣减成功,剩余的库存为:4
分布式锁释放
扣减成功,剩余的库存为:2
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放

8021模块日志

powershell 复制代码
扣减成功,剩余的库存为:82
分布式锁释放
扣减成功,剩余的库存为:79
分布式锁释放
扣减成功,剩余的库存为:77
分布式锁释放
扣减成功,剩余的库存为:74
分布式锁释放
扣减成功,剩余的库存为:73
分布式锁释放
扣减成功,剩余的库存为:71
分布式锁释放
扣减成功,剩余的库存为:70
分布式锁释放
扣减成功,剩余的库存为:69
分布式锁释放
扣减成功,剩余的库存为:67
分布式锁释放
扣减成功,剩余的库存为:65
分布式锁释放
扣减成功,剩余的库存为:63
分布式锁释放
扣减成功,剩余的库存为:61
分布式锁释放
扣减成功,剩余的库存为:59
分布式锁释放
扣减成功,剩余的库存为:57
分布式锁释放
扣减成功,剩余的库存为:55
分布式锁释放
扣减成功,剩余的库存为:53
分布式锁释放
扣减成功,剩余的库存为:51
分布式锁释放
扣减成功,剩余的库存为:49
分布式锁释放
扣减成功,剩余的库存为:47
分布式锁释放
扣减成功,剩余的库存为:45
分布式锁释放
扣减成功,剩余的库存为:43
分布式锁释放
扣减成功,剩余的库存为:41
分布式锁释放
扣减成功,剩余的库存为:39
分布式锁释放
扣减成功,剩余的库存为:37
分布式锁释放
扣减成功,剩余的库存为:35
分布式锁释放
扣减成功,剩余的库存为:33
分布式锁释放
扣减成功,剩余的库存为:31
分布式锁释放
扣减成功,剩余的库存为:29
分布式锁释放
扣减成功,剩余的库存为:27
分布式锁释放
扣减成功,剩余的库存为:25
分布式锁释放
扣减成功,剩余的库存为:23
分布式锁释放
扣减成功,剩余的库存为:21
分布式锁释放
扣减成功,剩余的库存为:19
分布式锁释放
扣减成功,剩余的库存为:17
分布式锁释放
扣减成功,剩余的库存为:15
分布式锁释放
扣减成功,剩余的库存为:13
分布式锁释放
扣减成功,剩余的库存为:11
分布式锁释放
扣减成功,剩余的库存为:9
分布式锁释放
扣减成功,剩余的库存为:7
分布式锁释放
扣减成功,剩余的库存为:5
分布式锁释放
扣减成功,剩余的库存为:3
分布式锁释放
扣减成功,剩余的库存为:1
分布式锁释放
扣减成功,剩余的库存为:0
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放
扣减库存失败,库存不足
分布式锁释放

可以看到,没有超卖现象。至此Redission实现分布式锁已经OK。

redis实现分布式锁 可见博文:【分布式锁】Redis实现分布式锁

相关推荐
老葱头蒸鸡4 小时前
(3)Kafka生产者分区策略、ISR、ACK、一致性语义
分布式·kafka
毕设源码-赖学姐5 小时前
【开题答辩全过程】以基于Hadoop的电商数据分析系统为例,包含答辩的问题和答案
大数据·hadoop·分布式·1024程序员节
ink@re5 小时前
消息队列集群——RabbitMQ
分布式·rabbitmq·1024程序员节
逻极9 小时前
HarmonyOS 5 鸿蒙多设备适配与分布式开发指南
分布式·华为·harmonyos·鸿蒙
OxYGC16 小时前
[RabbitMQ] 最新版本深度解析:4.0+ 新特性、性能飞跃与生产实践(2025 年更新)
分布式·rabbitmq
武子康16 小时前
Java-154 深入浅出 MongoDB 用Java访问 MongoDB 数据库 从环境搭建到CRUD完整示例
java·数据库·分布式·sql·mongodb·性能优化·nosql
Q飞了1 天前
分布式存储Ceph与OpenStack、RAID的关系
分布式·ceph·openstack
回家路上绕了弯1 天前
深入浅出:如何设计一个可靠的分布式 ID 生成器
分布式·后端
阿什么名字不会重复呢1 天前
Hadoop报错 Couldn‘t find datanode to read file from. Forbidden
大数据·hadoop·分布式