redis java实现秒杀
1 设置秒杀商品
提供一个接口给前端,当有秒杀商品上架的时候,完善好商品的信息之后,设置为秒杀商品,设置秒杀开始时间,通过DelayQueuq延迟队列,定时上架,可以秒杀,在redis中set一个key,key值为商品id+Flag,例如‘10000Flag’,值为0,表示未开始秒杀,防止被用户恶意提前开始抢购。
redis代码
redisTemplate.opsForValue().set("10000Flag","0");
redis中再放置一个key/list 数据,key为商品id,list中的值为商品id,list的长度为商品设置的秒杀数量,每一个list中的值称为令牌,也就是秒杀的门票。
int goodsNum = 10;
for(int i = 0; i < goodsNum; i++){ redisTemplate.opsForList().leftPush("10000","10000");
}
2 秒杀接口
先要判断是否可以开始秒杀了,一个用户只能秒杀一次,所以要判断用户是否已经秒杀过,通过redis给用户设置一把分布式锁,用setIfAbesent设置,key为商品id+用户id,值为当前时间戳,还未生成订单,1为生成订单,2为已完成,生成订单后,这把锁的获取时间就没有用了。
//2.0操作
String flag = redisTemplate.opsForValue().get("10000");
if("0".equals(flag)){//还不可以开始秒杀return;
}
//2.1操作
Boolean lockFlag = redisTemplate.opsForValue().setIfAbsent("goodId"+"userId", System.currentTimeMillis()+"",600, TimeUnit.SECONDS);
if(lockFlag){//获得锁 可以继续 判断商品数量
}
当用户拿到锁了,再判断秒杀商品的数量
//2.2操作
String good = redisTemplate.opsForList().leftPop("10000");
if(good != null){//说明还有商品 可以秒杀 否则返回秒杀商品已售完//2.3 生成订单 订单中包含商品id和用户id 去支付//订单生成完毕redisTemplate.opsForValue().set("商品id"+"用户id","1");
}
3 用户取消支付
定时任务判断用户支付状态,当用户超过支付截止时间+30s(30s为了预防网络延迟因素)未支付,则设置状态为取消,此时通过订单记录里的商品id和用户id,删除掉用户的锁
redisTemplate.delete("商品id"+"用户id");
并且将取得的list中的令牌还回去。其他用户可以继续秒杀。
redisTemplate.opsForList().leftPush("商品id","商品id");
4 支付完成
redisTemplate.opsForValue().set("商品id"+"用户id","2");
5 清理redis数据
定时任务去清理,秒杀第二天0点的时候去批量删除数据
//删除商品是否开始秒杀标签
redisTemplate.delete("商品id"+"Flag");
//删除商品数量
redisTemplate.delete("商品id");
6 问题
当程序在2.3用户创建订单之前,获取锁之后挂了,这时候这个用户又进来了,但是锁已经存在了,怎么处理,还得保证上一次用户获取这个锁的时间间隔不能太短。
//2.1操作
Boolean lockFlag = redisTemplate.opsForValue().setIfAbsent("goodId"+"userId","0",600, TimeUnit.SECONDS);
if(!lockFlag){//没获得锁String timeValue = redisTemplate.opsForValue().get("goodId"+"userId");// timeValue.length() 说明不是1和2 还未生成订单if(timeValue.length() > 1){Long oldTime = Long.parseLong(timeValue);if(oldTime - System.currentTimeMillis() < 5000){//距离第一次生成分布式锁过去不足5s返回系统繁忙,请等待return;}}//根据商品id+用户id 查询订单//如果存在 直接返回if(timeValue.length() > 1 || hasOrder){return;}//不存在 加锁 加在类上synchronized(Demo.class){//再判断是否有订单 有直接返回 没有继续。if(timeValue.length() > 1 || hasOrder){return;}}
}
//如果没有提前结束 就表明这个用户没有订单,用户经过登陆验证,认为是可靠的,这个分布式锁是可重入的,可以继续由这个用户使用。
如果2.2操作 即获取商品令牌之后,生成订单之前挂了,用户再次进来,不应该再去减库存,应该直接去生成订单的操作,所以当商品令牌扣减之后,讲用户和令牌绑定在一起。
//2.2操作
String good = redisTemplate.opsForValue().get("goodId"+"userId");
//是否需要拿商品令牌
Boolean flag = true;
if( "商品id".equals(good)){//说明还未生成订单,但是商品的令牌已经拿到了,根据用户id和商品id去查询if(hasOrder){return;}synchronized(Demo.class){if(hasOrder || good.length == 1){return;}else{flag = false;}}
}
if(flag){good = redisTemplate.opsForList().leftPop("10000");if(good == null){//秒杀商品已售完。return;}
}
//说明还有商品 可以秒杀 否则返回秒杀商品已售完
redisTemplate.opsForValue().set("商品id"+"用户id", good);
//2.3 生成订单 订单中包含商品id和用户id 去支付
//订单生成完毕
redisTemplate.opsForValue().set("商品id"+"用户id","1");
redis java实现秒杀相关推荐
- Spring Boot + redis解决商品秒杀库存超卖,看这篇文章就够了
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:涛哥谈篮球 来源:toutiao.com/i68366119 ...
- Redis轻松实现秒杀系统
点击关注公众号,实用技术文章及时了解 什么是秒杀 秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到.对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量 ...
- Redis 基础 - 优惠券秒杀《初步优化(异步秒杀)》
Redis基础 - 基本类型及常用命令 Redis基础 - Java客户端 Redis 基础 - 短信验证码登录 Redis 基础 - 用Redis查询商户信息 Redis 基础 - 优惠券秒杀< ...
- Redis 基础 - 优惠券秒杀《分布式锁(初级)》
参考 Redis基础 - 基本类型及常用命令 Redis基础 - Java客户端 Redis 基础 - 短信验证码登录 Redis 基础 - 用Redis查询商户信息 Redis 基础 - 优惠券秒杀 ...
- Java商品秒杀抢购模拟双十一基础版
Java秒杀抢购 需要用到的技术 java多线程 Redis mysql数据库 Quartz定时器 用到的框架: SSM 整体项目结构: 前端页面不用我们写,我这里提源码项目自己下载 链接:https ...
- redis如何解决秒杀超卖java_Spring Boot + redis解决商品秒杀库存超卖,看这篇文章就够了...
作者:涛哥谈篮球 来源:toutiao.com/i6836611989607809548 问题描述 在众多抢购活动中,在有限的商品数量的限制下如何保证抢购到商品的用户数不能大于商品数量,也就是不能出现 ...
- redis java客户端配置,Java的Redis客户端选择-jedis与Lettuce
Lettuce 和 Jedis 的定位都是Redis的client,所以他们当然可以直接连接redis server. Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线 ...
- Redis java客户端操作
jedis jedis官方指定的redis java客户端,将其导入到pom.xml问价内 <!-- https://mvnrepository.com/artifact/redis.clien ...
- Redis Java调用
Redis Java调用 package com.stono.redis;import redis.clients.jedis.Jedis;public class RedisJava {public ...
最新文章
- loadrunner用javavuser进行接口测试
- R语言ggplot2可视化强制指定X轴的日期范围实战:组合条形图和lm模型构建的回归模型的结果并强制指定X轴的日期范围
- 自己编写linux系统,自己动手 编写Linux系统的设备驱动程序
- 本周日,王海峰、朱军、李宏毅等大咖邀你加入这场AI开发者盛宴
- sublime text3支持Vue语法高亮显示步骤(转)
- error: not found: value SparkSession
- MySQL基础原创笔记(一)
- 进程间通信-Queue 消息队列 先进先出
- 关于JSP(Java Server Pages)的内置对象有哪些?
- 调用谷歌的方法输出图表,运行中的结果
- sqlmap的篡改绕过WAF
- Notepad++实现verilog语法检查
- python导入栈包
- 呼叫中心-自动外呼接口设置
- 众多的.ts文件、.key文件、.m3u8文件,合并成一个完整的mp4格式的视频
- 光流传感器 定位精度_基于多传感器的无人机定位和避障技术研究
- 什么叫结构化的算法?为什么要提倡结构化的算法?
- 11--字符流缓冲区编码表
- swift使用相机拍照
- 用Arduino实现精准电池电量电压指示器
热门文章
- C# error MSB3171: 生成清单时出现问题。未能加载文件或程序集,Windows.winmd
- java赵云主角兵器谱游戏_完美武将:赵云兵器大盘点
- 信安、网安保研夏令营分享(同济,华师,东南、复旦、中科大、北航)
- 应广单片机红外发射例程
- linux6.5ibm存储挂载,ESXI 6.7利用ISCSI挂载联想V3500存储的方法
- 透析Spring2---第三章试读
- 2.4G+5.8G双频5GWiFi网络分析仪警用追踪mac地址探针路由器下连接设备查看
- 思维导图制作软件|mindmanager 2012 10.1汉化版 下载地址
- 0xc000007b无法正常启动
- hooks taro 下拉刷新_小程序自定义下拉刷新(Taro版)