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,不受内存限制
相关推荐
李慕婉学姐33 分钟前
【开题答辩过程】以《基于Spring Boot和大数据的医院挂号系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
大数据·spring boot·后端
源代码•宸1 小时前
Leetcode—3. 无重复字符的最长子串【中等】
经验分享·后端·算法·leetcode·面试·golang·string
0和1的舞者2 小时前
基于Spring的论坛系统-前置知识
java·后端·spring·系统·开发·知识
invicinble3 小时前
对于springboot
java·spring boot·后端
码界奇点3 小时前
基于Spring Boot与Vue的校园后台管理系统设计与实现
vue.js·spring boot·后端·毕业设计·源代码管理
爱编程的小庄3 小时前
Rust 发行版本及工具介绍
开发语言·后端·rust
Apifox.5 小时前
测试用例越堆越多?用 Apifox 测试套件让自动化回归更易维护
运维·前端·后端·测试工具·单元测试·自动化·测试用例
sunnyday04265 小时前
Nginx与Spring Cloud Gateway QPS统计全攻略
java·spring boot·后端·nginx
康王有点困5 小时前
Link入门
后端·flink
海南java第二人5 小时前
Spring Boot全局异常处理终极指南:打造优雅的API错误响应体系
java·spring boot·后端