好好学习,天天向上
本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star
- 畅购商城(一):环境搭建
- 畅购商城(二):分布式文件系统FastDFS
- 畅购商城(三):商品管理
- 畅购商城(四):Lua、OpenResty、Canal实现广告缓存与同步
- 畅购商城(五):Elasticsearch实现商品搜索
- 畅购商城(六):商品搜索
- 畅购商城(七):Thymeleaf实现静态页
- 畅购商城(八):微服务网关和JWT令牌
- 畅购商城(九):Spring Security Oauth2
- 畅购商城(十):购物车
- 畅购商城(十一):订单
- 畅购商城(十二):接入微信支付
- 畅购商城(十三):秒杀系统「上」
- 畅购商城(十四):秒杀系统「下」
防止秒杀重复排队
回顾一下上一篇文章中讲到的下单的流程。当用户点击下单之后,用户名和商品id就会组装成一个SeckillStatus对象存入Redis队列中等待被处理,这个过程叫做排队。所以说,只要用户点击了一次下单后不论最后是否下单成功,他都会进入到排队的状态。如果用户重复点击下单,那么Redis队列中就会有很多个相同的SeckillStatus对象,也就是一个用户排队多次,这显然是不符合逻辑的,一个用户应该只能排队一次。
为了避免用户重复排队的情况,可以为每个用户在Redis中设置一个自增值,每次排队的时候加1,如果大于1,说明重复排队了,那么直接抛出异常,告诉用户重复排队了。
//SeckillOrderServiceImpl
@Override
public boolean add(Long id, String time, String username) {
Long increment = redisTemplate.boundHashOps(SystemConstants.SEC_KILL_USER_QUEUE_COUNT).increment(username, 1);
if (increment>1) { //记录指定hashkey的增量,大于1说明排队次数超过1次,重复排队
throw new RuntimeException("重复排队");
}
…………
}
这段代码中,添加了对用户重复排队的判断,先自增1,再进行判断。这里的key设置的是username,因为一个用户只能下单一件商品,如果去下单其它商品,同样也是重复排队。
测试了一下,是成功的。但是有一个问题:如果用户在这里排队未成功,该怎么清理排队信息呢?这个下一步就会说,接着往下看