系列文章目录
`
刚入门Java的硕士宝宝,实验室没什么Java项目,看到网上的秒杀项目,跟着学习并且记录一下,可能错误会很多,欢迎大家指正。
前言
本文介绍服务优化模块,具体详细介绍RabbitMQ的使用、接口优化。
`
一、RabbitMQ
RabbitMQ 是一个开源的消息代理软件,实现了高级消息队列协议(AMQP)标准,广泛应用于分布式系统中,用于实现消息的发布与订阅、消息的队列和路由、消息的确认和重试等功能。
RabbitMQ的使用
- 添加依赖:
<!-- AMQP依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- 配置类:
@Configuration
public class RabbitMQConfig {
@Bean
public Queue queue(){
return new Queue("queue",true);
}
}
- 发送消息:
@Service
@Slf4j
public class MQSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(Object msg) {
log.info("发送消息:"+msg);
rabbitTemplate.convertAndSend("queue", msg);
}
}
- 接收消息:
@Service
@Slf4j
public class MQReceiver {
@RabbitListener(queues = "queue")
public void receive(Object msg) {
log.info("接受消息:" + msg);
}
}
- 测试发送RabbitMQ消息:
@RequestMapping("/mq")
@ResponseBody
public void mq() {
mqSender.send("Hello");
}
二、RabbitMQ 交换机
- Fanout模式
不处理路由键,只需要简单的将队里绑定到交换机上;
发送到交换机的消息都会被转发到与该交换机绑定的所有队列上;
Fanout交换机转发消息是最快的。
- Direct模式
所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue;
Direct模式可以使用RabbitMQ自带的Exchange:default Exchange,所以不需要将Exchange进行任何绑定(binding)操作,消息传递时,RouteKey必须完全匹配才会被队列接收,否则该消息会被抛弃;
routing key与队列queues 的key保持一致,即可以路由到对应的queue。
- Topic模式
所有发送到Topic Exchange的消息被转发到所有管线RouteKey中指定Topic的Queue上;
Exchange将RouteKey和某Topic进行模糊匹配,此时队列需要绑定一个Topic。
- Headers模式
不依赖routingkey,使用发送消息时basicProperties对象中的headers匹配队列;
headers是一个键值对类型,键值对的值可以是任何类型;
在队列绑定交换机时用x-match来指定,all代表定义的多个键值对都要满足,any则代表只要满足一个可以了。
三、接口优化
总目标:减少数据库访问
- 系统初始化,把商品库存数量加载到Redis
- 收到请求,Redis预减库存。库存不足,直接返回。否则进入第3步
- 请求入队,立即返回排队中
- 请求出队,生成订单,减少库存
- 客户端轮询,是否秒杀成功
RabbitMQ秒杀
@Configuration
public class RabbitMQConfig {
private static final String QUEUE = "seckillQueue";
private static final String EXCHANGE = "seckillExchange";
@Bean
public Queue queue(){
return new Queue(QUEUE);
}
@Bean
public TopicExchange topicExchange(){
return new TopicExchange(EXCHANGE);
}
@Bean
public Binding binding01(){
return BindingBuilder.bind(queue()).to(topicExchange()).with("seckill.#");
}
}
@Service
@Slf4j
public class MQSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendsecKillMessage(String message) {
log.info("发送消息:" + message);
rabbitTemplate.convertAndSend("seckillExchange", "seckill.msg", message);
}
}
@Service
@Slf4j
public class MQReceiver {
@Autowired
private IGoodsService goodsService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private IOrderService orderService;
@RabbitListener(queues = "seckillQueue")
public void receive(String msg) {
log.info("QUEUE接受消息:" + msg);
SeckillMessage message = JsonUtil.jsonStr2Object(msg, SeckillMessage.class);
Long goodsId = message.getGoodsId();
User user = message.getUser();
GoodsVo goods = goodsService.findGoodsVoByGoodsId(goodsId);
//判断库存
if (goods.getStockCount() < 1) {
return;
}
String seckillOrderJson = (String)
redisTemplate.opsForValue().get("order:" + user.getId() + ":" + goodsId);
if (!StringUtils.isEmpty(seckillOrderJson)) {
return;
}
orderService.seckill(user, goods);
}
}
总结
以上就是今天要讲的内容,本文简单介绍了服务优化模块,具体参考 乐字节 Java电商秒杀项目。