Java 异步解决一人一单问题

思路

  1. 先判断用户是否有购买资格:

    1.1 商品优惠的起始时间当前时间做对比

    1.2 判断商品库存是否充足

  2. 判断用户是否拥有购买资格后,根据redis存入的内容,返回答复信息

  3. 需要更新的内容:如商品数量,订单详细... 存入缓存队列,异步的去数据库更新

代码

1. 判断用户资格

下图为秒杀方法,秒杀的商品为限时购物券,传入的参数为购物券id。只有在规定起始期限内,且库存充足的前提下才能够抢购。

判断用户具有购买资格后,为其创建订单。

代码底部逻辑为:获取当前登录的用户id,假设为1,对每个用户的id加锁,避免同一用户在同一时刻多次抢单成功。

userId.toString().intern()为重点:

使用锁的本意是,将id值一样的用户加上一把锁 , 确保一人一单。

但是每一个请求来,id对象都是一个全新的id对象,因此对象变了,锁就变了。

要求值一样,所以使用toString(),将对象转化为字符串。而toString()的本质其实还是新建了一个字符串,本质上还是新建了个新的对象。如每次抢单时用户id都是1,虽然id号一样,但是都还是不同的对象。

而inter()的作用是去字符串常量池找到值一样的字符串地址,那么无论new了多少个字符串,只要是值一样,那锁存入的便都是相同的地址。

2. 执行脚本,将订单信息存入缓存队列

首先解释下为什么要用脚本,直接写逻辑不好吗?

因为在一条脚本中编写多条redis命令,可以确保命令执行的一致性,确保了数据的一致性。

事实上,使用脚本之后,上面对用户Id加锁都不需要写了。

脚本代码:

3.将缓存队列中的对象存入数据库

ps: 缓存队列与消息队列区别

名称 缓存队列 消息队列
特点 jdk阻塞队列:使用的jvm的内存,若不加以限制,无数对象加以创建放入阻塞队列,可能会导致内存溢出,需要设置队列的上限。若满,无法放入。存在数量的限制。若宕机,内存的数据消失,存在数据安全问题。若任务从队列后取出,出现异常,那么任务再也不会处理。 独立于jvm,不受内存限制
相关推荐
李慕婉学姐2 小时前
Springboot旅游景点管理系统2fj40iq6(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
蓝眸少年CY2 小时前
(第八篇)spring cloud之zuul路由网关
后端·spring·spring cloud
long3162 小时前
弗洛伊德·沃肖算法 Floyd Warshall Algorithm
java·后端·算法·spring·springboot·图论
Loo国昌2 小时前
【LangChain1.0】第一篇:基础认知
后端·python·算法·语言模型·prompt
源代码•宸2 小时前
Golang原理剖析(channel面试与分析)
开发语言·经验分享·后端·面试·golang·select·channel
鹿角片ljp3 小时前
Java多线程编程:从基础到实战的完整指南
java·开发语言·后端
rannn_1113 小时前
【Javaweb学习|Day6】日志技术、多表查询、分页查询及优化(动态SQL)
java·后端·javaweb
qq_12498707534 小时前
基于微信小程序的宠物寄领养系统(源码+论文+部署+安装)
java·spring boot·后端·微信小程序·小程序·宠物·计算机毕业设计
那我掉的头发算什么4 小时前
【SpringBoot】从创建第一个spring项目开始
spring boot·后端·spring
源代码•宸4 小时前
Golang原理剖析(channel源码分析)
开发语言·后端·golang·select·channel·hchan·sudog