基于RocketMQ设计秒杀

tech2022-08-12  129

文章内容输出来源:拉勾教育Java高薪训练营

环境介绍

服务器: 阿里云Centos7.4

JDK版本: jdk1.8 RocketMQ版本: 4.5.1

安装RocketMQ

wget https://archive.apache.org/dist/rocketmq/4.5.1/rocketmq-all-4.5.1-bin-release.zip

启动nameserver

# 1.启动 NameServermqnamesrv # 2.查看启动日志 tail -f ~/logs/rocketmqlogs/namesrv.log

启动broker

mqbroker -n localhost:9876 # 2.查看启动日志 tail -f ~/logs/rocketmqlogs/broker.log

基于RocketMQ设计秒杀实现逻辑

这里的超时支付使用redis过期回调处理

核心代码 :

@Component @RocketMQMessageListener(topic = "springboot-mq",consumerGroup = "springboot-mq-consumer-1") public class Consumer implements RocketMQListener<OrderInfo> { @Resource OrderInfoMapper orderInfoMapper; @Resource WarehouseMapper warehouseMapper; @Autowired StringRedisTemplate redisTemplate; @Override public void onMessage(OrderInfo orderInfo) { System.out.println("消费订单消息"); orderInfoMapper.insert(orderInfo); System.out.println(orderInfo.getId()+"订单入库"); Warehouse warehouse = warehouseMapper.selectByPrimaryKey(orderInfo.getCommodity()); warehouse.setNum(warehouse.getNum()-1); System.out.println("扣减库存"); warehouseMapper.updateByPrimaryKey(warehouse); redisTemplate.opsForValue().set("order:"+orderInfo.getId(),"",15,TimeUnit.SECONDS); } } @Component public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener { @Resource OrderInfoMapper orderInfoMapper; @Resource WarehouseMapper warehouseMapper; @Autowired StringRedisTemplate redisTemplate; public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) { super(listenerContainer); } public void onMessage(Message message, byte[] pattern) { String expireKey = message.toString(); if (expireKey.startsWith("order:")){ Integer orderId = Integer.valueOf(expireKey.replace("order:","")); OrderInfo orderInfo = orderInfoMapper.selectByPrimaryKey(orderId); orderInfo.setStatus(2); orderInfoMapper.updateByPrimaryKeySelective(orderInfo); System.out.println("订单失效,库存还原+1"); Warehouse warehouse = warehouseMapper.selectByPrimaryKey(orderInfo.getCommodity()); warehouse.setNum(warehouse.getNum()+1); warehouseMapper.updateByPrimaryKey(warehouse); redisTemplate.opsForValue().increment("num"); } } } @Service public class OrderService { @Resource OrderInfoMapper orderInfoMapper; @Autowired StringRedisTemplate redisTemplate; @Autowired private RocketMQTemplate rocketMQTemplate; public Integer submitOrder(Integer commodity){ Integer id = getOrderNum(); OrderInfo orderInfo = new OrderInfo(); orderInfo.setId(id); orderInfo.setCommodity(commodity); orderInfo.setStatus(0); boolean flag = subtractStock(1); if(!flag){ return -1; } rocketMQTemplate.convertAndSend("springboot-mq",orderInfo); return id; } public Integer pay(Integer id){ Boolean delete = redisTemplate.delete("order:" + id); System.out.println(delete); if(delete){ return 1; } return 0; } /** * 模拟订单号 * @return */ public Integer getOrderNum(){ Random random = new Random(); return random.nextInt(10000); } /** * Redis乐观锁实现秒杀 * @param num * @return */ public boolean subtractStock(Integer num) { String key = "num"; redisTemplate.setEnableTransactionSupport(true); redisTemplate.watch(key); Object value = redisTemplate.opsForValue().get(key); if (value == null) { //前提 提前将商品库存放入缓存 ,如果缓存不存在,视为没有该商品 return false; } //先检查 库存是否充足 Integer stock = Integer.valueOf(value.toString()); if (stock < num) { System.out.println("库存不足"); return false; } redisTemplate.multi(); Long newStock = redisTemplate.opsForValue().increment(key, -num.longValue()); System.out.println(newStock); List<Object> exec = redisTemplate.exec(); if(exec!=null && exec.size()>0){ return true; } return false; } }

写在最后 工作几年,一直都没有去体系化的学习,很多东西没有复杂的工作场景经验,去年综合几家机构,最后还是决定报了拉勾的高薪训练营,在这里也是实实在在的学习到了很多,学完掌握程度也比之前深了很多,而且还有定期的内推,多了更多的机会,真的对我有了很大的帮助提升。

最新回复(0)