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 支付成功 微信 ...
随机推荐
- 【STM32】如何将资源烧写至外部flash,如spi-flash
STM32将资源烧写至外部flash方式大致分为通过IDE与应用程序一起和通过CubeProgranmmer单独烧写两种: 方式一.使用IDE加载烧写算法,烧录应用程序时一并写入,具体就是修改分散加载 ...
- Laravel - Eloquent 删除数据
public function ormDelete() { # 1.通过模型删除 // $student = Student::where('id',5 ...
- [转帖]HBase实战:记一次Safepoint导致长时间STW的踩坑之旅
https://mp.weixin.qq.com/s/GEwD1B-XqFIudWP_EbGgdQ 过 程 记 录 现象:小米有一个比较大的公共离线HBase集群,用户很多,每天有大量的Ma ...
- [转帖]加速拥抱支持开源生态 | OceanBase 开源版3.1.1正式发布
https://www.oceanbase.com/news/accelerated-embrace-and-support-of-open-source-ecosystem-oceanbase-op ...
- [转帖]Harbor:修改默认的172网段
背景: harbor 默认启动会随机创建 172 网段的ip地址,跟集群规划的网段冲突 Harbor 网段修改步骤 0. 原来Harbor占用的网段 # 网桥名:harbor_harbor [root ...
- [转帖]ssd/san/sas/磁盘/光纤/RAID性能比较
https://plantegg.github.io/2022/01/25/ssd_san%E5%92%8Csas%E7%A3%81%E7%9B%98%E6%80%A7%E8%83%BD%E6%AF% ...
- [转帖]Linux系统awk命令详解
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具. 之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 ...
- 一次典型的Memroy Leak的跟踪学习过程
背景 周四时某项目在QQ群里说自己的系统出现了CPU占用较高的情况. TOP 查看发现大部分占用CPU的都是 JAVA核心进城后附近的进程. 所以初步怀疑 是出现了FullGC的问题. 然后群里反馈了 ...
- Oracle 设置白名单过滤
最近有一个需求 要求开发人员不能随便连接测试的数据库 又不想太过复杂,部分人还得进行连结. 查了下往上是有方案的: 就是 TCP_VALIDNODE_CHECKING 参数 解决方法和说明如下 来源 ...
- 没有虚拟DOM版本的vue(Vue Vapor)
前言 随着Svelte和SolidJS的流行,无虚拟DOM模式逐渐开始火了起来.vue也推出了无虚拟DOM模式的版本,就是我们今天要讲的Vue Vapor. 什么是Vue Vapor Vue Vapo ...