当前位置:网站首页>Redis秒杀demo
Redis秒杀demo
2022-07-01 15:24:00 【y_w_x_k】
方案一:方法上加上synchronized即可,线程安全方案,但是执行效率较低,不适合大型并发场合
方案二:采用乐观锁
controller:
@RestController
public class SecondKill {
@Autowired
SecondKillSev secondKillSev;
@RequestMapping(value = "/buy",method = RequestMethod.POST)
public Mes buy(@RequestParam("proid") String proid){
String usedId=new Random().nextInt(1000)+"";
Mes mes = secondKillSev.doSecondKill(usedId, proid);
return mes;
}
}service:
@Service
public class SecondKillSev {
Mes message;
public SecondKillSev(){
}
@Autowired
StringRedisTemplate stringRedisTemplate;
/**
* 执行秒杀
* 方案一:synchronized,线程安全,但是执行效率较低,不适合大型并发场合
* 方案二:用乐观锁监听事务
*/
public Mes doSecondKill(String uid, String proid){
//1.判断uid和proid非空
if(uid==null || proid==null){
return Mes.getMes("400","uid和proid不能为空");
}
//2.连接redis
ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
//3.拼接key,库存key,成功用户key
String kcKey="kcKey:"+proid;
String userKey="userKey:"+proid;
//乐观锁解决超卖问题
//stringRedisTemplate默认不开启事物
stringRedisTemplate.setEnableTransactionSupport(true);
List<Object> txResults = stringRedisTemplate.execute(new SessionCallback<List<Object>>() {
public List<Object> execute(RedisOperations operations) throws DataAccessException {
//监视库存
operations.watch(kcKey);
//4.获取库存,如果库存是null,则秒杀还没开始
String kc=ops.get(kcKey);
if(kc==null){
message= Mes.getMes("400","库存是null,秒杀还没开始");
return null;
}
//5.判断用户是否重复秒杀
if(operations.opsForSet().isMember(userKey, uid)){
message=Mes.getMes("400","不能重复秒杀");
return null;
}
//6.判断商品数量,如果数量小于1,则秒杀结束
if(Integer.parseInt(kc)<=0){
message=Mes.getMes("400","秒杀已经结束");
return null;
}
//7.秒杀过程,库存-1,成功用户添加到清单
//使用事务
operations.multi();
operations.opsForValue().decrement(kcKey);
operations.opsForSet().add(userKey,uid);
List exec = operations.exec();
if(exec==null || exec.size()==0){
message=Mes.getMes("400","秒杀失败");
return null;
}else{
return exec;
}
}
});
if(txResults==null ||txResults.size()==0){
return message;
}
return Mes.getMes("200","秒杀成功");
}
}
但是这种方案也有一个缺点,就是如果商品的数量是500,但是线程数是1000,即访问量不是非常多的情况下,会出现库存没有卖完的问题,即库存遗留问题,所以可以用lua脚本来解决;
方案三:lua脚本
local userid=KEYS[1];
local prodid=KEYS[2];
local qtkey="sk:"..prodid..":qt";
local userskey="sk:"..prodid..":user";
local userExists=redis.call("sismember",userskey,userid);
if tonumber(userExists)==1 then
return 2;
end
local num=redis.call("get",qtkey);
if tonumber(num)<=0 then
return 0;
else
redis.call("decr",qtkey);
redis.call("sadd",userskey,userid);
end
return 1
代码实现:
@Service
public class SeckillByScript {
static String secKillScript1 = "local userid=KEYS[1];\n" +
"local prodid=KEYS[2];\n" +
"local qtkey=\"sk:\"..prodid..\":qt\";\n" +
"local userskey=\"sk:\"..prodid..\":user\";\n" +
"local userExists=redis.call(\"sismember\",userskey,userid);" +
"if tonumber(userExists)==1 then\n" +
" return 2;\n" +
"end\n" +
"local num=redis.call(\"get\",qtkey);\n" +
"if tonumber(num)<=0 then\n" +
" return 0;\n" +
"else\n" +
" redis.call(\"decr\",qtkey);\n" +
" redis.call(\"sadd\",userskey,userid);\n" +
" end\n" +
" return 1";
public boolean doSecKill(String userid, String prodid) {
JedisPool jedisPool = JedisPoolUtil.getJedisPool();
Jedis jedis = jedisPool.getResource();
String sha1 = jedis.scriptLoad(secKillScript1);
Object result = jedis.evalsha(sha1, 2, userid, prodid);
String reString = String.valueOf(result);
if ("0".equals(reString)) {
System.out.println("已抢空!");
return false;
} else if ("1".equals(reString)) {
System.out.println("抢购成功");
return true;
} else if ("2".equals(reString)) {
System.out.println("该用户已抢过!");
return false;
} else {
System.out.println("抢购异常");
return false;
}
}
}
边栏推荐
- Configuration of ZABBIX API and PHP
- 选择在长城证券上炒股开户可以吗?安全吗?
- 《QT+PCL第六章》点云配准icp系列4
- Apk signature principle
- 微信小程序03-文字一左一右显示,行内块元素居中
- Solid basic structure and array, private / public function, return value and modifier of function, event
- A unifying review of deep and shallow anomaly detection
- 使用swiper制作手机端轮播图
- Junda technology - wechat cloud monitoring scheme for multiple precision air conditioners
- MySQL 服务正在启动 MySQL 服务无法启动解决途径
猜你喜欢

微信网页订阅消息实现

Phpcms background upload picture button cannot be clicked

厦门灌口镇田头村特色农产品 甜头村特色农产品蚂蚁新村7.1答案

《QT+PCL第九章》点云重建系列2

【目标跟踪】|STARK
![Opencv Learning Notes 6 -- image feature [harris+sift]+ feature matching](/img/50/5c8adacea78e470c255070c8621ddd.png)
Opencv Learning Notes 6 -- image feature [harris+sift]+ feature matching

Filter & (login interception)

Returning to the top of the list, the ID is still weak

做空蔚来的灰熊,以“碰瓷”中概股为生?

The solution to turn the newly created XML file into a common file in idea
随机推荐
【ROS进阶篇】第五讲 ROS中的TF坐标变换
Configuration of ZABBIX API and PHP
【STM32-USB-MSC问题求助】STM32F411CEU6 (WeAct)+w25q64+USB-MSC Flash用SPI2 读出容量只有520KB
【一天学awk】函数与自定义函数
说明 | 华为云云商店「商品推荐榜」
项目中字符串判空总结
Using swiper to make mobile phone rotation map
opencv学习笔记六--图像特征[harris+SIFT]+特征匹配
重回榜首的大众,ID依然乏力
【300+精选大厂面试题持续分享】大数据运维尖刀面试题专栏(三)
What if you are always bullied because you are too honest in the workplace?
SAP CRM organization Model(组织架构模型)自动决定的逻辑分析
Connect the ABAP on premises system to the central inspection system for custom code migration
张驰咨询:家电企业用六西格玛项目减少客户非合理退货案例
贝联珠贯加入龙蜥社区,共同促进碳中和
Logical analysis of automatic decision of SAP CRM organization model
[antenna] [3] some shortcut keys of CST
Qt+pcl Chapter 6 point cloud registration ICP Series 2
Task. Run(), Task. Factory. Analysis of behavior inconsistency between startnew() and new task()
Opencv learning note 4 -- bank card number recognition