Redis实战(黑马点评--优惠券秒杀)
一、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("库存不足"); }
想都是问题,做都是答案,站着不动永远是观众。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体