大家平时在做有并发量下单的项目时,代码层面基本上就分为这么几个步骤:参数校验--->防重校验--->库存校验扣减--->下单成功--->支付。
最近公司有个商城项目说要30分钟达到1亿的并发量。当时听到突然猛了一下。真是牛逼克拉斯呀。
不过该说不说还是得开搞,所谓的并发无非就是要想办法减少io的操作,尽量少查表,其余配置方面的问题就看公司舍不舍得花钱了。
其中防重校验这一部分选用了redis集合lua来做,来防止多次提交。
注意:真实下单操作是分为了订单前置操作 (前置校验和生成防重令牌)和提交订单两个接口来写的,这里为了测试简单合并了
@RestController
@RequestMapping("/lua")
public class TestLuaController {
@Autowired
private StringRedisTemplate redisTemplate;
private static final String ORDER_CHECK_TOKEN = "order_check_token";
private static final String ORDER_TOKEN_DEFAULT_VALUE = "value";
/**
* 场景:最近公司有高并发场景,涉及到用令牌防重(防止有人多次提交订单)
* 可以使用redis执行lua脚本 比较key值令牌是否存在,如果存在即删除
*/
@RequestMapping("/checkTempToken")
public Long luaExecute(String checkToken){
//模拟提交订单生成的防重令牌
redisTemplate.opsForValue().set(ORDER_CHECK_TOKEN + checkToken,ORDER_TOKEN_DEFAULT_VALUE,60, TimeUnit.SECONDS);
String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
"then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
//执行redis脚本操作的函数
Long execute = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(ORDER_CHECK_TOKEN + checkToken), ORDER_TOKEN_DEFAULT_VALUE);
System.out.println(execute);
return execute;
}
}
结果: