一、介绍MQ全称为MessageQueue——消息队列,是一种应用程序到应用程序的消息通信。阅读消息,发布者无需关心谁阅读了消息,读者也无需关心谁发布了消息,各司其职,互不干扰。市场上常用的消息队列有:RabbitMQ、RocketMQ、Kafka、ActiveMQ。2、MQ的优点(1)解耦使用消息MQ后,只需要保证消息格式不变,不需要关心发布者和消费者之间的关系,两者不需要相互沟通。(2)异步在一些不需要立即(同步)返回结果的操作中,异步是通过消息队列来实现的。(3)当调峰期间(尖峰场景)有大量请求时,通过消息队列进行缓冲,削弱高峰流量,防止系统在短时间内被高峰流量压垮。场景:在大流量高峰期,如果数据库只能承受2000个并发流量,可以使用MQ控制2000个到数据库。(4)日志处理日志存储在消息队列中,用于处理日志,如Kafka。3、MQ的缺点是降低了系统的可用性。在引入MQ之前,系统只需要关心生产端和消费端的接口一致性即可。现在引入之后,系统需要注意生产端、MQ、消费端的稳定性。这增加了系统的负担,增加了系统运维成本。随着MQ的引入,随着系统复杂度的增加,需要考虑更多的问题,比如如何保证消息的一致性,如何防止重复消费等。一致性问题系统A发送消息后直接返回成功,但是如果BCD系统中有任何一个系统写入数据库失败,就会出现数据不一致。4.常见问题(1)如何保证消息不被重复消费?如何使用消息队列保证幂等性?幂等性:即用户对同一操作发起的一次请求或多次请求的结果是一致的,不会因多次请求而导致。点击有副作用。问题原因我们先来了解下消息重复消费的原因。对于MQ的使用,分为三个角色:producer、MQ、consumer。那么就会出现消息的重复:Producer:Producer可能会向MQ发送重复的数据,有可能是controller接口重复提交了两次,也有可能是重试机制导致的。MQ:假设网络出现波动,consumer消费消息后,发送ack时,MQ还没来得及接受,突然挂了,导致MQ认为consumer还没消费完消息,MQ回复消息后会再次推送这条消息,造成重复消费。Consumer:消费者收到消息后,准备向MQ发送ack。突然,消费者挂了,还没有发送ack。这时候MQ就认为消费者还没有消费消息。消费者重启后,MQ再次向其推送消息。解决方案一般情况下,生产者就是客户,我们很难避免用户重复点击的情况。MQ允许多条相同的消息,但是不允许消费者消费两条相同的数据,所以一般在消费者端实现幂等:状态判断:消费者将消费消息记录在redis中,再次消费时,先去redis中进行判断数据是否存在。如果存在,就说明已经被消费掉了,直接丢弃。业务判断:数据被消费后,需要插入数据库,利用数据库的唯一性约束,防止重复消费。在将数据插入数据库之前检查数据是否存在,如果存在则丢弃该消息。这种方法是比较简单粗暴的解决问题的方法。(2)消息丢失的情况(3)消息发送顺序性的解决方法生产者发布消息时,每次未发布消息时,都会在消息体中记录上一条消息的ID。消费者收到消息后,进行如下操作。首先根据之前的Id查看是否有之前的消息没有被消费过。如果不存在(消费后去掉id),则正常进行。如果正常运行。如果存在,则根据id去数据库查看是否被消费,如果被消费,则正常运行。如果还没有消费,它会休眠一定时间(比如30ms),然后再检查。如果它被消耗,它将正常运行。如果尚未消费,则抛出异常。(4)如何解决百万消息的积压问题根据消息的重要性,分为两种情况:如果消息可以丢弃,那么直接丢弃。一般情况下,消息是不能丢弃的,所以需要考虑策略,我们可以重新把原来的消费者作为生产端,重新部署一天MQ,稍后再添加消费端,形成另一个生产-message-消费线。
