减缓存 添加队列
@ResponseBody
@RequestMapping("/{path}/domiaosha")
public ResultBean findall(@RequestParam("goodsId") Long goodsId, @PathVariable String path, User user, long addresssId) throws Exception {
if (user == null) {
return ResultBean.error(AbnoNum.USERNAME_IS_ENIST);
}
try {
//验证path是否通过
boolean b = miaoshaOrderService.checkPath(user.getId(), goodsId, path);
if (!b) {
return ResultBean.error(AbnoNum.REQUEST);
}
//内存标记 减少redis访问
Boolean boo = localmap.get(goodsId);
if (boo) {
return ResultBean.error(AbnoNum.MIAOSHAGOODS_IS_ENIST);
}
//预减库存
Long stock = stringRedisTemplate.opsForValue().decrement(MiaoShaGoodKey.MiaoshaGoodskucun.getPrefix() + goodsId, 1);
if (stock < 0) {
localmap.put(goodsId, true);
return ResultBean.error(AbnoNum.MIAOSHAGOODS_IS_ENIST);
}
//判断是否秒杀到了
MiaoshaOrder miaoshaOrder = miaoshaOrderService.getMiaoShaUserByUserIdAndGoodsId(user.getId(), goodsId);
if (miaoshaOrder != null) {
stringRedisTemplate.opsForValue().increment(MiaoShaGoodKey.MiaoshaGoodskucun.getPrefix() + goodsId, 1);
return ResultBean.error(AbnoNum.ORDER_REPEAT);
}
} catch (Exception e) {
//最后一个商品下单出现错误 数据库减少库存失败了 redis 减少成功
stringRedisTemplate.opsForValue().increment(MiaoShaGoodKey.MiaoshaGoodskucun.getPrefix() + goodsId, 1);
return ResultBean.error(AbnoNum.order_error);
}
Future<?> future = executors.submit(new Runnable() {
@Override
public void run() {
MiaoShaMessage miaoShaMessage = new MiaoShaMessage();
miaoShaMessage.setGoodsId(goodsId);
miaoShaMessage.setUser(user);
miaoShaMessage.setAddresssId(addresssId);
sendMessage.sendDirectMessage(miaoShaMessage);
}
});
return ResultBean.success(0);
}
rabbitmq配置
```package com.etc.rabbitMq.MQsender;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author Mr.findelist
* @program: seckillplus
* @Date 2020/8/7 10:33
**/
@Configuration
public class DirectRabbitConfig {
//队列 起名:TestDirectQueue
@Bean
public Queue TestDirectQueue() {
// durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
// exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
// autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
// return new Queue("TestDirectQueue",true,true,false);
//一般设置一下队列的持久化就好,其余两个就是默认false
return new Queue("TestDirectQueue",true);
}
//Direct交换机 起名:TestDirectExchange
@Bean
DirectExchange TestDirectExchange() {
// return new DirectExchange("TestDirectExchange",true,true);
return new DirectExchange("TestDirectExchange",true,false);
}
//绑定 将队列和交换机绑定, 并设置用于匹配键:TestDirectRouting
@Bean
Binding bindingDirect() {
return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("TestDirectRouting");
}
}
发送到队列的方法
package com.etc.rabbitMq.MQsender;
import com.alibaba.fastjson.JSON;
import com.etc.domian.MiaoShaMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Author Mr.findelist
* @program: seckillplus
* @Date 2020/8/7 10:36
**/
@Service
public class SendMessage {
@Autowired
RabbitTemplate rabbitTemplate;
//使用RabbitTemplate,这提供了接收/发送等等方法
public void sendDirectMessage(MiaoShaMessage miaoShaMessage) {
String s = JSON.toJSONString(miaoShaMessage);
//将消息携带绑定键值:TestDirectRouting 发送到交换机TestDirectExchange
rabbitTemplate.convertAndSend("TestDirectExchange", "TestDirectRouting", s);
}
}
处理消息
package com.etc.rabbitMq.MQsender;
import com.alibaba.fastjson.JSON;
import com.etc.domian.MiaoShaMessage;
import com.etc.domian.MiaoshaOrder;
import com.etc.service.impl.MiaoshaGoodsServiceImpl;
import com.etc.service.impl.MiaoshaOrderServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Author Mr.findelist
* @program: seckillplus
* @Date 2020/8/7 10:43
**/
@Slf4j
@Service
@RabbitListener(queues = "TestDirectQueue")//监听的队列名称 TestDirectQueue
public class DirectReceiver {
@Autowired
MiaoshaGoodsServiceImpl goodsService;
@Autowired
MiaoshaOrderServiceImpl miaoshaOrderService;
@Autowired
MiaoshaGoodsServiceImpl miaoshaGoodsService;
@RabbitHandler
public void process(String msg) {
log.info("DirectReceiver消费者收到消息 : " + msg);
MiaoShaMessage ms = JSON.parseObject(msg, MiaoShaMessage.class);
//数据库商品库存
Integer goodsStockById = goodsService.findGoodsStockById(ms.getGoodsId());
if (goodsStockById <= 0) {
return;
}
//是否重复秒杀
MiaoshaOrder miaoshaOrder = miaoshaOrderService.getMiaoShaUserByUserIdAndGoodsId(ms.getUser().getId(), ms.getGoodsId());
if (miaoshaOrder != null) {
return;
}
miaoshaOrderService.miaoSha(ms.getUser(),ms.getGoodsId(),ms.getAddresssId());
}
}