Redis+Lua实现简易的秒杀抢购
1 商品抢购
主要逻辑是:减库存,记录抢购成功的用户
@RestController
public class DemoController {
@Resource
private StringRedisTemplate stringRedisTemplate;
private static final String GOODS_STOCK_KEY = "goods:001"; // 秒杀商品库存
private static final String GOODS_USER_KEY = "users:001"; // 抢购成功的用户列表
/**
* 在不加锁的情况下,会发生超卖
*/
@GetMapping("/seckill")
public String seckill() {
int userId = (int) (Math.random() * 1000);
ValueOperations valueOps = stringRedisTemplate.opsForValue();
ListOperations listOps = stringRedisTemplate.opsForList();
int stock = Integer.parseInt(valueOps.get(GOODS_STOCK_KEY));
if (stock > 0) {
valueOps.decrement(GOODS_STOCK_KEY);
listOps.leftPush(GOODS_USER_KEY, String.valueOf(userId));
return "抢购成功";
} else {
return "商品已售罄";
}
}
/**
* 将多个命令打包成一个原子操作,利用redis单线程执行命令的特性,在不加锁的情况下避免了资源竞争
*/
@GetMapping("/seckill_lua")
public String seckill_lua() {
int userId = (int) (Math.random() * 1000);
String script = "if tonumber(redis.call('get', KEYS[1])) > 0 then " +
"redis.call('decr', KEYS[1]); " +
"redis.call('lpush', KEYS[2], ARGV[1]); " +
"return 1; " +
"else " +
"return 0; " +
"end; ";
DefaultRedisScript redisScript = new DefaultRedisScript();
redisScript.setResultType(Long.class);
redisScript.setScriptText(script);
List keyList = Arrays.asList(GOODS_STOCK_KEY, GOODS_USER_KEY);
Long result = stringRedisTemplate.execute(redisScript, keyList, String.valueOf(userId));
if (result == 1) {
return "抢购成功";
} else {
return "商品已售罄";
}
}
}
对比两次的结果:

2 多线程处理Excel导入
/**
* 多线程处理Excel导入
*
* PS:
* Executors返回的线程池对象的弊端如下:
* (1) FixedThreadPool和SingleThreadPool: 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
* (2) CachedThreadPool: 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
*/
@PostMapping
public void excelImport() throws InterruptedException {
// 待处理的数据(比如:从Excel中读取的数据)
List dataList = new ArrayList();
// 多线程处理
ExecutorService executorService = Executors.newFixedThreadPool(5);
CountDownLatch countDownLatch = new CountDownLatch(dataList.size());
for (Object obj : dataList) {
executorService.submit(new Runnable() {
@Override
public void run() {
try {
} catch (Exception ex) {
} finally {
countDownLatch.countDown();
}
}
});
}
countDownLatch.await(30, TimeUnit.SECONDS);
// 后续执行
// 返回结果
}
Redis+Lua实现简易的秒杀抢购的更多相关文章
- Redis+Lua解决高并发场景抢购秒杀问题
之前写了一篇PHP+Redis链表解决高并发下商品超卖问题,今天介绍一些如何使用PHP+Redis+Lua解决高并发下商品超卖问题. 为何要使用Lua脚本解决商品超卖的问题呢? Redis在2.6版本 ...
- spring boot:redis+lua实现生产环境中可用的秒杀功能(spring boot 2.2.0)
一,秒杀需要具备的功能: 秒杀通常是电商中用到的吸引流量的促销活动方式 搭建秒杀系统,需要具备以下几点: 1,限制每个用户购买的商品数量,(秒杀价格为吸引流量一般会订的很低,不能让一个用户全部抢购到手 ...
- redis使用watch完成秒杀抢购功能
Redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...
- redis使用watch完成秒杀抢购功能(转)
redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...
- redis使用watch完成秒杀抢购功能:
redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内 ...
- php结合Redis实现高并发下的秒杀抢购功能
实现思路 准备两个队列A和B,假设A队列的名称为stock,用于存放商品总库存信息,B队列的名称为users,用于存放抢购成功后的用户信息.每当有用户进行抢购操作时,先从A队列弹出一个元素,如果该元素 ...
- 【高并发】Redis如何助力高并发秒杀系统,看完这篇我彻底懂了!!
写在前面 之前,我们在<[高并发]高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!>一文中,详细讲解了高并发秒杀系统的架构设计,其中,我们介绍了可以使用Redis存储秒杀商品的库存数量.很 ...
- redis watch 加 事务实现秒杀
<?php //redis watch 加 事务实现秒杀 $redis = new redis(); $result = $redis->connect('10.10.10.119 ...
- 利用 JS 脚本实现网页全自动秒杀抢购
利用 JS 脚本实现网页全自动秒杀抢购 倒计时页面: 倒计时未结束时,购买按钮还不能点击. 结束时,可以点击购买,点击后出现提示"付款成功" 展示效果 1.制作测试网页 首先我们来 ...
- SpringCloud(十一)- 秒杀 抢购
1.流程图 1.1 数据预热 1.2 抢购 1.3 生成订单 (发送订单消息) 1.4 订单入库 (监听 消费订单消息) 1.5 查看订单状态 1.6 支付 (获取支付链接 ) 1.7 支付成功 微信 ...
随机推荐
- SQL函数——时间函数
1.使用 NOW() . CURDATE().CURTIME() 获取当前时间 在这里我有一个问题想问问大家,你们平时都是怎么样子获取时间的呢?是不是通过手表.手机.电脑等设备了解到的,那么你们有没有 ...
- 【Tomcat 组成与工作原理】
Tomcat组成与工作原理 Tomcat 是什么 开源的 Java Web 应用服务器,实现了 Java EE(Java Platform Enterprise Edition)的部 分技术规范,比如 ...
- 百度网盘(百度云)SVIP超级会员共享账号每日更新(2023.12.11)
一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...
- SpringBoot开启动态定时任务并手动、自动关闭
场景需求:在执行某个方法的两小时之后进行某个操作 涉及:定时任务.哈希表 需要注意:业务逻辑层是单一实例的,所以在定时任务类内操作业务逻辑层的某个属性和在业务逻辑层内操作的都是同一个. 疑问:Thre ...
- [转帖]为什么 Java 内部使用 UTF-16 表示字符串?
https://www.jianshu.com/p/957b249a02d8 背景 许多年前 Unicode 的提出者天真地以为 16 位定长的字符可以容纳地球上所有仍具活力的文字,Java 设计者也 ...
- 关于JVM指针压缩性能的研究
关于JVM指针压缩性能的研究 摘要 JVM的内存对消最小是 8bytes 所以32G内存的情况下可以使用 32位的指针就可以了. 32位就是4G 在乘以最小的内存extent 8 bytes 的出来可 ...
- [转帖]Java连接 MySQL详细教程,分享复习经验和后台开发面经
(由于安装了汉化包,英文版的用户可以对应图标来操作) 选中菜单栏文件,之后选择项目结构 选择Libraries 点击+ :使用 NMT 协助排查内存问题案例
https://www.modb.pro/db/557714 从前面几篇文章,我们了解了 NMT 的基础知识以及 NMT 追踪区域分析的相关内容,本篇文章将为大家介绍一下使用 NMT 协助排查内存问题 ...
- [转帖]apt update和apt upgrade命令 - 有什么区别?
在之前的文章中,我们查看了APT 命令以及您可以使用包管理器来管理包的各种方法.这是一个总体概述,但在本指南中,我们暂停并重点关注 2 个命令用法.这些是apt update和apt upgrade命 ...
- [粘贴]【CPU】关于x86、x86_64/x64、amd64和arm64/aarch64
[CPU]关于x86.x86_64/x64.amd64和arm64/aarch64 https://www.jianshu.com/p/2753c45af9bf 为什么叫x86和x86_64和AMD6 ...