消息队列&中间件

时间:2024-03-12 14:12:33

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");
    }
}

----未完待续----