一、redis实现全局唯一订单id
1、问题:使用数据库自增id不合适
当用户抢购商品时,生成的订单会保存到tb_voucher_order
表中,而订单表如果使用数据库自增ID就会存在一些问题
- id规律性太明显
- 受单表数据量的限制
2、解决方法:全局id生成器
- 符号位:1bit,永远为0
- 时间戳:31bit,以秒为单位,可以使用69年(2^31秒约等于69年)
- 序列号:32bit,秒内的计数器,支持每秒传输2^32个不同ID
@Component public class RedisIdWorker { @Autowired private StringRedisTemplate stringRedisTemplate; //设置起始时间,我这里设定的是2022.01.01 00:00:00 public static final Long BEGIN_TIMESTAMP = 1640995200L; //序列号长度 public static final Long COUNT_BIT = 32L; public long nextId(String keyPrefix){ //1. 生成时间戳 LocalDateTime now = LocalDateTime.now(); long currentSecond = now.toEpochSecond(ZoneOffset.UTC); long timeStamp = currentSecond - BEGIN_TIMESTAMP; //2. 生成序列号 String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd")); long count = stringRedisTemplate.opsForValue().increment("inc:"+keyPrefix+":"+date); //3. 拼接并返回,简单位运算 return timeStamp << COUNT_BIT | count; } public static void main(String[] args) { //设置一下起始时间,时间戳就是起始时间与当前时间的秒数差 LocalDateTime tmp = LocalDateTime.of(2022, 1, 1, 0, 0, 0); System.out.println(tmp.toEpochSecond(ZoneOffset.UTC)); //结果为1640995200L } }
二、实现秒杀下单
脑图:
1、出现的问题(最后一张票时):多线程并行查询库存后,再减库存,会导致超卖。
2、解决方法:乐观锁,执行更新库存时,先比较:查询到的优惠券库存和实际数据库中优惠券库存是否相同
// 5.扣减库存 boolean success = seckillVoucherService.update().setSql("stock = stock - 1") // set stock = stock - 1 .eq("voucher_id", voucherId).eq("stock", voucher.getStock()) // where id = ? and stock = ? .update(); if (!success) { return Result.fail("库存不足"); }
- 以上逻辑的核心含义是:只要我扣减库存时的库存和之前我查询到的库存是一样的,就意味着没有人在中间修改过库存,那么此时就是安全的,但是以上这种方式通过测试发现会有很多失败的情况,失败的原因在于:在使用乐观锁过程中假设100个线程同时都拿到了100的库存,然后大家一起去进行扣减,但是100个人中只有1个人能扣减成功,其他的人在处理时,他们在扣减时,库存已经被修改过了,所以此时其他线程都会失败
- 那么我们继续完善代码,修改我们的逻辑,在这种场景,我们可以只判断是否有剩余优惠券,即只要数据库中的库存大于0,都能顺利完成扣减库存操作
// 5.扣减库存 boolean success = seckillVoucherService.update().setSql("stock = stock - 1") // set stock = stock - 1 .eq("voucher_id", voucherId) //.eq("stock", voucher.getStock()) // where id = ? and stock = ? .gt("stock", 0) .update(); if (!success) { return Result.fail("库存不足"); }
标签:优惠券,扣减,--,Redis,库存,voucher,id,stock From: https://www.cnblogs.com/fengok/p/17872938.html