黑马点评学习笔记11(Redission)

前言

前面介绍了基于Redis实现分布式锁来解决优惠券秒杀系统中的高并发问题。通过SET key value NX PX命令实现互斥锁,结合Spring的setIfAbsent方法封装锁获取逻辑。实现中需要注意锁的过期时间设置以避免死锁,以及事务处理保证数据一致性。该方案有效解决了JVM单机锁在分布式环境下的局限性。

经过上面的优化,我们实现的分布式锁已经达到生产可用级别了,但是还不够完善,比如:

来看看怎么解决吧

像上面一步优化分布式锁,太麻烦了,可以直接使用已经实现好的Redission'。

来看看什么是Redission吧

Redisson 是一个基于 Java 的 Redis 客户端 ,它不仅提供了对 Redis 原生命令的封装,更重要的是在 Redis 的基础上实现了一系列分布式对象、服务和工具,使得开发者可以像使用本地 Java 对象一样操作分布式环境中的共享资源。Redisson 的设计目标是简化分布式系统开发,提供线程安全、高性能、高可用的分布式解决方案。

Redisson实现分布式锁

1)引入Redisson依赖

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

2)配置Redisson客户端

java 复制代码
package com.hmdp.config;

import ...

@Configuration
public class RedissonConfig {

    @Bean
    public RedissonClient redissonClient() {
        // 创建配置
        Config config = new Config();
        config.useSingleServer().setAddress("redis://localhost:6379");//我的Redis是本地的,要改成自己的如果有密码记得配置
        // 创建RedissonClient对象
        return Redisson.create(config);
    }
}

4)Redission的使用:其实就是换一个锁把我们自己写的RedisIdWorker锁换成刚刚配置的redisson锁

java 复制代码
package com.hmdp.service.impl;

import ...

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Slf4j
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {

    @Resource
    private ISeckillVoucherService seckillVoucherService;

    @Resource
    private RedisIdWorker redisIdWorker;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RedissonClient redissonClient;

   
 /*
    查询领取秒杀券
     */
    @Override
    public Result seckillVoucher(Long voucherId) {
        //1.查询优惠券
        SeckillVoucher voucher = seckillVoucherService.getById(voucherId);

        //2.判断秒杀是否开始
        if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {
            return Result.fail("秒杀尚未开始");
        }

        //3.判断秒杀是否结束
        if (voucher.getEndTime().isBefore(LocalDateTime.now())) {
            return Result.fail("秒杀已结束");
        }

        //4.判断库存是否充足
        if (voucher.getStock() < 1) {
            return Result.fail("库存不足");
        }

 
        // 3、创建订单(使用分布式锁)
        Long userId = ThreadLocalUtls.getUser().getId();
        RLock lock = redissonClient.getLock(RedisConstants.LOCK_ORDER_KEY + userId);
        boolean isLock = lock.tryLock();

        if (!isLock) {
            // 索取锁失败,重试或者直接抛异常(这个业务是一人一单,所以直接返回失败信息)
            return Result.fail("一人只能下一单");
        }
        try {
            // 索取锁成功,创建代理对象,使用代理对象调用第三方事务方法, 防止事务失效
            IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
            return proxy.createVoucherOrder(userId, voucherId);
        } finally {
            lock.unLock();
        }



    }


      /*
//    创建订单
//     */
    @Transactional  //添加事务保证数据库操作和缓存操作的原子性
    public void createVoucherOrder(VoucherOrder voucherOrder) {
        //5.一人一单
        //5.1 查询订单
        Long userId = voucherOrder.getUserId();

            //5.1 获取锁成功

            int count = query().eq("user_id", userId).eq("voucher_id", voucherOrder).count();
            //5.2.判断是否存在
            if (count > 0) {
                //用户购买过
                log.error("用户已经买过了");
                return ;
            }

            //6.扣减库存
            boolean success = seckillVoucherService.update()
                    .setSql("stock = stock - 1")
                    .eq("voucher_id", voucherOrder)
                    .gt("stock", 0)//where id = ? and stock > 0
                    .update();

            if (!success) {
                //扣减库存失败
                log.error("库存不足");
                return ;
            }

            //写入数据库
            save(voucherOrder);

    }
}

所以其实最好的分布式锁,就是用别人写好包装好的🤪,一场酣畅淋漓的白雪。。。

本文是学习黑马程序员---黑马点评项目的课程笔记,小白啊!!!写的不好轻喷啊🤯如果觉得写的不好,点个赞吧🤪(批评是我写作的动力)

...。。。。。。。。。。。...

...。。。。。。。。。。。...

相关推荐
点心的游戏开发世界9 小时前
GDScript 入门笔记(十一):Lambda 与匿名函数
开发语言·笔记·游戏引擎·godot
摇滚侠9 小时前
《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 使用 JdbcTemplate 阅读笔记 32
spring boot·笔记·后端
sunshine22 girl10 小时前
Java学习一 环境配置2 安装和基本使用Idea
java·学习·intellij-idea
鱼子星_11 小时前
【C++】继承和多态(上)
c++·笔记
Kobebryant-Manba11 小时前
学习Bert微调
人工智能·学习·bert
xian_wwq11 小时前
【学习笔记】深度认知系列-第14讲 端侧AI崛起——为什么AI正在从云端走向本地
人工智能·笔记·学习
我爱cope12 小时前
【计算机网络 | 传输层3:TCP 协议概述:面向连接、可靠传输到底意味着什么?】
网络·网络协议·学习·tcp/ip·计算机网络·传输层
策案案案13 小时前
YOLO: 将AI Agents嵌入到IntelliJ IDEA
java·大数据·人工智能·笔记·yolo·microsoft·intellij-idea
代码的小搬运工13 小时前
KVO学习
学习·ios·cocoa
辣知14 小时前
辣知·化智47 黄帝陵与民族精神归途
学习