关于优惠券秒杀问题

1. 秒杀

1.1 全局唯一ID

全局ID生成器,是一种在分布式系统下用来生成全局唯一ID的工具,一般要满足下列特性:

唯一性、高性能、安全性、递增性、高可用

为了使ID更加安全,不会直接使用Redis自增的数值,而是拼接其他信息
在这里插入图片描述
成部分:符号位:1bit,永远为0
时间戳:31bit,以秒为单位,可以使用69年
序列号:32bit,秒内的计数器,支持每秒产生2^32个不同ID

1.2 使用Redis生成全局唯一Id(使用Redis实现ID自增长 increment(key))

@Component
public class RedisIdWorker {
    private static final long BEGIN_TIMESTAMP = 1640995200L; //设置开始时间戳
    private static final int COUNT_BITS = 32;//序列号位数
    //使用构造方法注入Redis
    private StringRedisTemplate stringRedisTemplate; 
    public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public long nextId(String keyPrefix) {
        // 1.生成时间戳
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        long timestamp = nowSecond - BEGIN_TIMESTAMP;  //时间戳相减,获取新的时间戳

        // 2.生成序列号
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));// 获取当前日期,精确到天(格式化)
        long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);  // 使用Redis实现ID自增长  increment(key)

        // 3.拼接并返回  timestamp左移32位,再与count相与   有1则1
        return timestamp << COUNT_BITS | count;
    }
}

2. 解决优惠券超卖问题

2.0 悲观锁和乐观锁

针对这一问题的常见解决方案就是加锁:而对于加锁,我们通常有两种解决方案

  • 悲观锁:任务线程安全问题一定会发生,在操作数据之前先获取锁,确保线程串行执行
    • 例如:Synchronized、Lock都属于悲观锁
      • 优点:简单粗暴
      • 缺点:性能一般
  • 乐观锁:任务线程安全问题不一定发生,只是在更新数据时去判断有没有其他线程对数据进行了更改,针对可能发生的问题去加锁
    • 如果没有修改则任务是安全的,自己才能更新数据
    • 如果已经被其他线程修改说明发生了安全问题,此时可以重试或抛异常
      • 优点:性能好
      • 缺点:存在成功率低问题,并给数据库加大了压力

2.1 分析超卖问题原因

源码如下:

 if (voucher.getStock() < 1) {  // 库存不足
        return Result.fail("库存不足!");
    }
    boolean success = seckillVoucherService.update() //5,扣减库存
            .setSql("stock= stock -1")
            .eq("voucher_id", voucherId).update();
    if (!success) {  //判断扣减库存是否成功
        return Result.fail("库存不足!");
    }

假设线程1过来查询库存,判断出来库存大于1,正准备去扣减库存,但是还没有来得及去扣减,此时线程2过来,线程2也去查询库存,发现这个数量一定也大于1,那么这两个线程都会去扣减库存,最终多个线程相当于一起去扣减库存,此时就会出现库存的超卖问题。
在这里插入图片描述

2.2 使用乐观锁解决超卖问题

有两种方式:

  • 版本号法
  • CAS法
    在这里插入图片描述
    在这里插入图片描述
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值