ToB企服应用市场:ToB评测及商务社交产业平台
标题:
Redis+Lua实现简易的秒杀抢购
[打印本页]
作者:
花瓣小跑
时间:
2022-8-21 20:02
标题:
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<string, string=""> valueOps = stringRedisTemplate.opsForValue();
ListOperations<string, string=""> 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<long> redisScript = new DefaultRedisScript();
redisScript.setResultType(Long.class);
redisScript.setScriptText(script);
List<string> keyList = Arrays.asList(GOODS_STOCK_KEY, GOODS_USER_KEY);
Long result = stringRedisTemplate.execute(redisScript, keyList, String.valueOf(userId));
if (result == 1) {
return "抢购成功";
} else {
return "商品已售罄";
}
}
}</string></long></string,></string,>
复制代码
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);
// 后续执行
// 返回结果
}
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4