@Transactional
public BaseResponse spike(String phone, Long GoodsId) {
GoodsDto goodsDto = seckillMapper.getByGoodsId(GoodsId);
if (goodsDto == null) {
return setResultError(“商品信息不存在!”);
}
// 用户频率限制 setnx 如果key存在话
Boolean reusltNx = redisUtil.setNx(phone, seckillId + “”, 10l);
if (!reusltNx) {
return setResultError(“访问次数过多,10秒后再实现重试!”);// 直接return,无需执行下面的version++操作
}
Long version = goodsDto.getVersion();// 先获取版本号
int row = seckillMapper.inventoryDeduction(GoodsId, version);// 减库存
// 后续可以生成订单到订单表。。。
}
@Component
public class RedisUtil {
@Autowired
private StringRedisTemplate stringRedisTemplate;
// 如果key存在的话返回fasle 不存在的话返回true(原生redis的setNx命令会返回0或1)
public Boolean setNx(String key, String value, Long timeout) {
Boolean setIfAbsent = stringRedisTemplate.opsForValue().setIfAbsent(key, value);
if (timeout != null) {
stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
}
return setIfAbsent;
}
public void setList(String key, List<String> listToken) {
stringRedisTemplate.opsForList().leftPushAll(key, listToken);
}
}
 
**3. 基于库存令牌桶 + MQ 实现异步修改库存并提交订单**
在高并发情况下,如果有1万个用户同时秒杀某一商品,对数据库频繁的IO操作,可能会产生数据库崩溃问题(分表分库,读写分离治标不治本),解决方法:基于MQ+库存令牌桶实现。
同时有1万个请求实现秒杀,商品库存只有100个, 实现只需要修改库存100次就可以了:
方案实现流程:商品库存是多少,就提前在redis生成多少对应的库存令牌(这里即为100),在1万个请求中,只要谁能够获取到令牌谁就能够秒杀成功, 获取到秒杀令牌后,在使用mq异步实现修改减去库存。
代码实现:
**① 编写生成100个令牌桶接口**