如何使用RabbitMQ实现异步秒杀
作者:starrismq
这篇文章主要介绍了如何使用RabbitMQ实现异步秒杀,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
搭建RabbitMQ
在虚拟机上用docker搭建RabbitMQ,首先拉取镜像
docker run --privileged=true -d -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:management mkdir -p /usr/local/docker/rabbitmq
再创建rabbitmq容器,下面的命令已经能够创建之后直接启动了
docker run --privileged=true -d -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:management
启动之后,在浏览器中输入
http://192.168.200.130:15672/#/
->也就是http://你的虚拟机地址:15672
登录的密码以及账号默认都是guest
创建交换机以及queues
创建交换机
创建queues,名字为seckill.order.queue
创建好queue以及交换机后,回到交换机处,为交换机绑定一个queue,以便以后交换机接受到指定Rounting key的消息后,能够将信息交给指定queue来消费信息,实现消息队列(也就是将订单消息交给交换机,交换机将消息给到queue,queue收到消息后就能消费信息,使用订单信息完成扣减库存等)
在项目中应用RabbitMQ
1 引入amqp依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
2 配置连接信息
rabbitmq: host: 192.168.238.128 # 你的虚拟机IP port: 5672 # 端口 virtual-host: /dianping # 虚拟主机 username: guest # 用户名 password: guest # 密码 listener: direct: acknowledge-mode: manual
3 添加序列化配置
自定义RabbitMQ中json格式的消息的序列化机制
@Configuration public class RabbitMQConfig { @Bean public MessageConverter messageConverter() { return new Jackson2JsonMessageConverter(); } }
修改业务代码
直接将订单交给消息队列RabbitMQ
消息发送者
@Resource private RabbitTemplate rabbitTemplate;
@Transactional public void handleVoucherOrder(VoucherOrder voucherOrder) { //1.所有信息从当前消息实体中拿 Long voucherId = voucherOrder.getVoucherId(); //2.扣减库存 boolean success = seckillVoucherService.update().setSql("stock=stock-1") .eq("voucher_id", voucherId) //======判断当前库存是否大于0就可以决定是否能抢池子中的券了 .gt("stock", 0) .update(); //3.创建订单 save(voucherOrder); } @Override public Result seckillVoucher(Long voucherId) { //1.执行lua脚本,判断当前用户的购买资格 Long userId = ThreadLocalUtls.getUser().getId(); Long result = stringRedisTemplate.execute( SECKILL_SCRIPT, Collections.emptyList(), voucherId.toString(), userId.toString()); if (result != 0) { //2.不为0说明没有购买资格 return Result.fail(result==1?"库存不足":"不能重复下单"); } //3.走到这一步说明有购买资格,将订单信息存到阻塞队列 VoucherOrder voucherOrder = new VoucherOrder(); long orderId = redisIdWorker.nextId("order"); voucherOrder.setId(orderId); voucherOrder.setUserId(ThreadLocalUtls.getUser().getId()); voucherOrder.setVoucherId(voucherId); //存入消息队列等待异步消费 rabbitTemplate.convertAndSend("seckill.direct","seckill.order",voucherOrder); return Result.ok(orderId); }
消费者
创建一个Listener文件夹,创建消费者专门监听交换器,收到信息传来的订单就执行处理订单方法,调用VoucherOrderService中的handleVoucherOrder来处理订单,下单并修改数据库
@Component public class SeckillOrderListener { @Autowired VoucherOrderServiceImpl voucherOrderService; @RabbitListener(queues = {"seckill.order.queue"}) public void recieveMessage(Message message, Channel channel, VoucherOrder voucherOrder){ try { voucherOrderService.handleVoucherOrder(voucherOrder); channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); } catch (IOException e) { throw new RuntimeException(e); } }
到此这篇关于使用RabbitMQ实现异步秒杀的文章就介绍到这了,更多相关RabbitMQ异步秒杀内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!