1.什么是消息队列?
消息队列,我们一般称为MQ(Message Queue)。
很多初学者认为MQ通过消息的发送和接受来实现程序的异步和解耦,但是实际上MQ的主要目的是通讯。
MQ定义了发送者为生产者,接收消息的那一方为消费者。
2.消息队列的主要作用。
异步,削峰,解耦(重要)。
业务场景
假设一个下单的业务场景,用户在下单之后,需要依次完成扣减余额,扣减库存,通知商家,发送短信,发送京豆等业务。
高可用: 如果其中一个服务宕机(这里的宕机不一定是服务器故障,更多指的是网络延迟,网络缓慢的问题),那么后面的业务都不能执行下去,业务之间的耦合度高。
高并发: 线程数量是有限的,每次处理的请求数量是有限的。在QPS很高的情况,服务很容易被冲垮。
高性能: 上面业务都是串行执行,假设网络传输200ms,业务20ms,完成上面这些操作就要耗时2s,用户的体验极差。并且下单之后业务越多,这个时间越长。
传统设计
在说明消息队列的优势之前,需要先明确传统设计的不足之处。
传统设计的思路使用于并发量小,业务体量小的场景下,我们可以很快定位到程序中的错误,这是优势,但当并发量增大的情况下,会产生问题(三高)。
消息队列
如果采用消息队列,再来审视上面三个问题。
高可用: 其中一个模块宕机了,也不会影响其他模块。(假如库存系统宕掉了,那就等他好了之后再取消息消费,库存系统,短信服务还是各司其职)
高并发: 消息队列不处理业务上的逻辑,每次下单只需要把订单消息放到消息队列里面,并且消息队列支持的并发是百万级的,就不需要担心服务被冲垮这回事。
高性能: 用户下单,我们的逻辑就是放消息到消息队列中,请求很快就能返回,用户体验比较好。
消息队列的优点
解耦: 如上面高并发所说,一个服务宕了,不会影响其他服务。
削峰: 假设平时服务只能撑起来几万QPS,当遇到淘宝京东的秒杀活动,服务器直接垮掉。但是有了消息队列,只需要将下单消息放到消息队列中,其他服务从里面取出来正常消费即可,不至于把服务压垮。类似是一个大坝无拦截上游的冲击力。
异步: 连接消息队列的服务模块异步执行。多一个模块,不用改原来的代码,只相当于消息队列多一个消费者。
消息队列的问题
消息队列是完美的吗? 肯定不是,有优点就会有缺点。
第一,在并发量不大的情况下没必要用,反而让系统设计更加复杂。
第二,事务问题。也是最明显的问题。没办法保证所有业务都能执行成功,可能数据不一致(可能下单了,信息也发了,但是库存没减)。既然要用消息队列,就要接受这个问题的存在。只需要保证最终一致性,最终数据是正确的。
第三,可用性。解耦说的是业务模块之间的解耦,但是如果消息队列挂了,会影响所有模块。也就是其他模块对消息队列的依赖性很严重。
KafKa使用
1.添加依赖。
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
2.yml配置
spring:
kafka:
bootstrap-servers: 服务器ip:端口
consumer:
group-id: 组别名
3.生产者
@RestController
public class KafKaController {
@Autowired
KafkaTemplate kafkaTemplate;
@RequestMapping("/produce")
public String producer(String message){
kafkaTemplate.send("order",message);
return "生产者生产消息";
}
}
4.消费者监听
@Component
public class KafKaListen {//接收来自kafka的消息
@KafkaListener(topics = "order")
public void listen(ConsumerRecord<String,String> record){
System.out.println("接收到消息" + record.value());
System.out.println("okk");
}
}
----未完待续----