广告位联系
返回顶部
分享到

Redis实现限量优惠券的秒杀功能

Redis 来源:互联网 作者:佚名 发布时间:2024-12-04 21:43:37 人浏览
摘要

核心:避免超卖问题,保证一人一单 业务逻辑 代码步骤分析 全部代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

核心:避免超卖问题,保证一人一单  业务逻辑

代码步骤分析

全部代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

@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 seckillVoucher = seckillVoucherService.getById(voucherId);

        //2 判断秒杀是否开始

        LocalDateTime now = LocalDateTime.now(); //现在时间

        LocalDateTime beginTime = seckillVoucher.getBeginTime(); //开始时间

        LocalDateTime endTime = seckillVoucher.getEndTime(); //结束时间

        if (now.isBefore(beginTime)) {

            return Result.fail("秒杀还未开始");

        }

        //3 判断秒杀是否结束

        if (now.isAfter(endTime)) {

            return Result.fail("秒杀已结束");

        }

        //4 判断库存是否充足

        int stock = (int) seckillVoucher.getStock();

        if (stock == 0 && stock <= 0) {

            return Result.fail("库存不足");

        }

        //确保一人一单 用户ID和代金券ID联合查询

        Long userId = UserHolder.getUser().getId();

        //先获取锁 再提交事务

        //synchronized (userId.toString().intern()) {

        //创建锁对象

        //SimpleRedisLock simpleRedisLock = new SimpleRedisLock("order:" + userId, stringRedisTemplate);

        RLock lock = redissonClient.getLock("lock:order:" + userId);

        //获取锁

        boolean isLock = lock.tryLock();

        //判断是否获取锁成功

        if (!isLock){

            //获取锁失败 返回错误或失败

            return Result.fail("不允许重复下单");

        }

        try {

            //获取事务的代理对象

            IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();

            return proxy.creatVoucherOrder(voucherId);

        } finally {

            //释放锁

            lock.unlock();

        }

        //}//事务提交之后在释放锁

    }

    /**

     * 这里对于加锁做出一些解释:如果锁加在整个方法上,那么就会导

     *  致锁的粒度过大,导致每个进程进来都会锁住,所以要控制锁的粒度

     */

    @Transactional

    public Result creatVoucherOrder(Long voucherId) {

        Long userId = UserHolder.getUser().getId();

        Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();

        if (count > 0) {

            return Result.fail("用户已经购买过了");

        }

        //5 扣减库存-

        boolean success = seckillVoucherService.update()

                .setSql("stock = stock -1 ")  //乐观锁

                .eq("voucher_id", voucherId).gt("stock", 0) //判断库存是否大于0: where id = ? and stock > 0

                .update();

        if (!success) {

            return Result.fail("库存不足");

        }

        //6 创建订单

        //6.1 订单ID

        VoucherOrder voucherOrder = new VoucherOrder();

        long orderid = RedisIdWorker.nextId("order");

        voucherOrder.setVoucherId(orderid);

        //6.2 用户ID

        voucherOrder.setUserId(userId);

        //6.3 代金券ID

        voucherOrder.setVoucherId(voucherId);

        save(voucherOrder);

        //7 返回订单id

        return Result.ok(orderid);

    }

}


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • Linux环境下升级redis的详细步骤介绍

    Linux环境下升级redis的详细步骤介绍
    一、摘要 最近漏洞扫描服务器发现,Redis 缓冲区溢出漏洞(CVE-2024-31449),解决办法redis更新到6.2.16、7.2.6或7.4.1及以上版本。 二、漏洞描述 漏
  • Redis实现限量优惠券的秒杀功能

    Redis实现限量优惠券的秒杀功能
    核心:避免超卖问题,保证一人一单 业务逻辑 代码步骤分析 全部代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
  • redis缓存预热的实现介绍
    一、缓存预热的必要性 在一个高并发的系统中,如果缓存刚启动时是空的,所有的请求都会直接打到数据库,这可能会导致以下问题: 高延
  • Redis哈希槽的介绍
    1. 什么是 Redis 哈希槽? Redis Cluster 是 Redis 的分布式架构,它将数据分布在多个 Redis 实例(节点)上。为了实现数据分片,Redis Cluster 使用了
  • mysql中窗口函数lag()用法介绍
    在MySQL中,窗口函数LAG()可以用来访问当前行的前一行或多行的数据。这个函数通常用于分析时间序列数据,比如计算相邻行之间的差异或者
  • MySQL中group_concat函数用法小结

    MySQL中group_concat函数用法小结
    一、group_concat函数的功能 将group by产生的同一个分组中的值连接起来,返回一个字符串结果。group_concat函数首先根据group by指定的列进行分组
  • Redis模拟延时队列实现日程提醒的方法
    使用Redis模拟延时队列 实际上通过MQ实现延时队列更加方便,只是在实际业务中种种原因导致最终选择使用redis作为该业务实现的中间件,顺
  • mysql日常锁表之flush_tables介绍
    1. Flush tables简介 官方手册中关于Flush tables的介绍 Closes all open tables, forces all tables in use to be closed, and flushes the query cache. FLUSH TABLES also remove
  • Mysql中的secure_file_priv参数设置方法

    Mysql中的secure_file_priv参数设置方法
    secure_file_priv是MySQL中的系统变量,用于限制文件的读取和写入。 该参数的设置可以通过my.ini(windows版本)/my.cnf(Linux版本)中设置。 修改完参数
  • Redis数据一致性的介绍

    Redis数据一致性的介绍
    1、一致性 一致性是指系统中各节点数据保持一致。分布式系统中,可以理解为多个节点中的数据是一致的。 一致性根据严苛程度分类: 强
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计