总结一下这一年关于MQ消息队的感悟

861 阅读6分钟

为什么使用MQ?

解耦:

说道这个,就必须说一下我们在订单系统里面的一个场景,因为我们的订单服务是切分为了三个服务了,用户订单系统,师傅订单系统,总包服务商订单系统。而用户会下单给总包,总包会挑选一个师傅,下单给师傅,当师傅完成了任务,那么他肯定要通知到总包的订单系统,说我这边已经服务完成了,但是有一天,产品的需求改了,他需要师傅在服务完成的时候,不仅仅是要通知到总包服务商,也要通知到用户,那如果我们的系统使用的是调用接口API的形式,那么我们肯定要去添加对用户代码的依赖,并且调用用户的代码,而且用户也必须新增一个接口,这样的话耦合性太大,而且我们还必须考虑到如果一个服务挂掉了会怎么办?如果我们是发送MQ消息,那么我们只需要在用户端订阅MQ消息就可以了。所以使用MQ的第一个优势就是为了解耦。

异步:

比如说一个用户,他给一个师傅下单,但是这是一个微服务的架构,订单系统都是有用户订单系统和师傅订单系统的,那么如果这个下单的过程,它不仅仅是要调用用户订单服务,还要调用师傅订单服务,而且它可能还会调用其他类似的关联的服务,当服务一多,那么也就意味着要向多个数据库插入数据,那肯定就意味着响应速度大大的降低了,对用户的体验感是非常不好的,那这个时候如果我们如果使用MQ的话,那么我们可能只需要向用户订单服务的数据库新增数据,然后就可以直接返回了,而需要给调用其他系统的情况,我们转成MQ来发送,这样的话,响应速度将会大大的提高了。

削峰:

因为我们的系统,都是在白天的时候用户的使用比较频繁,但是晚上的时候,用的就比较少,但是如果我们的出现的最大的并发请求是2万条,但是晚上的时候,普遍又只有几百条,如果我们是将系统的数据库的性能设置到最高处理2万条,那么在晚上的时候,那性能无疑是大大的浪费了。所以我们需要MQ来进行削峰处理,也是用户每秒发过来2万条请求的时候,我们都是先写入到MQ里面,然后服务器只会恒定的每秒钟消费5000条,那么在高峰期的时候,服务器也能抗住高并发不会宕机,也不会对性能造成浪费。

RabbitMQ和kafka

RabbitMQ是万级的单机吐吞量,延迟比较低,微秒级别,并发能力比较强。但是不是分布式系统,只能做主从架构实现高可用,数据副本实际上还是只有一份。

Kafka的话是十万级别的吞吐量,但是功能是比较简单,最适合大数据领域。是分布式架构,一个数据有多个副本。

MQ的缺点

如果没有MQ消息队列,那么肯定就不会有当MQ服务宕机的时候,导致整体系统的宕机了。除了宕机这种情况,我们还要考虑到消息有没有重复消费,或者消息丢失了怎么办,或者说其他的服务都消费MQ成功了,但是偏偏还有一个服务消费MQ失败了,这等等一系列的问题。(需要保持最终一致性问题,并且要有业务监控系统。)

如何解决MQ的缺点

1.重复消费

因为消费者是隔一段时间来提交自己消费的消息的编号offset的,也就是说如果消费者突然宕机了,那么有可能有的消息已经消费了,但是没有提交到MQ那里让MQ知道,因此当消费者重启后,可能会导致消息的重复消费。 通过业务的判断,来保证代码业务的幂等性。

2.消息丢失

2.1生产者搞丢了数据

可能是因为网络或者其他的一些问题,导致生产者发送的MQ消息在半路就丢了,没有发送到mq那里去。

因此一般确保MQ消息不丢失,我们需要在生产者发送了MQ消息给MQ之后(MQ将消息持久化),需要MQ返回一个Ack消息给生产者,这样的话生产者就能保证自己的消息已经发送给MQ了,如果一段时间内MQ没有回传消息给到生产者,那么生产者可以选择重发消息。

2.2 mq弄丢了消息

可能是因为mq宕机了等等一系列的问题,导致mq的消息丢失了,那么这个时候要开启mq的持久化,将mq消息持久化到磁盘上,这样即使是mq宕机了,也不影响。

2.3 消费者将消息搞丢了

一般来说,当消费者消费到一条消息后,会通知MQ说我已经消费到这条消息了,但是如果消费这条消息而且正在处理的时候,消费者宕机了,那么就会导致消息丢失。 消费者应该在消费到消息并且已经处理完了,再通知MQ。(rabbitMQ关掉autoAck模式)(如果是kafka,需要关闭自动提交offset,那么也是在处理完消息后,再返回offset。)

3.如果保持MQ消息的顺序性

rabbitMQ在mq里面创建多个队列queue,保证一个队列queue只被一个消费者消费,这样的话就能保证消息的顺序性。

Kafka中可以指定一个key,保证这个key对应的mq消息是进入到一个partition中去,而一个partiton在kafka中是规定了只被一个消费者消费,这样就能保证mq消息的顺序性了。

4.消息队列里面堆积了几百万消息

4.1

堆积了太多的消息,rabbitMQ里面消息会过期。因此需要只能在晚上来补偿这些消息

4.2

kafka堆积了太多消息,那么只能紧急扩容消费端,扩大消费端的消费能力。也可以新建一个topic,partition数量是之前的10倍,然后一个partition只能对应一个消费端,然后又将消费端的性能扩容,紧急的赶紧把这些消息消费掉。当这些消息消费完了之后,再使用之前的架构来消费。