MQ
MQ的作用
- 解耦:将各个系统解耦,降低各系统之间的耦合性。
- 异步:之前的一个业务操作可能需要整个操作完成后返回一个结果,整个操作完成很耗时。使用mq后可以将请求放到队列中,让消费者去队列消费对应的消息。对于用户来说提升了用户体验。
- 削峰:高峰期大量操作涌入系统会导致数据库崩溃,使用mq后可以将大量请求放入队列中,让系统从队列中根据最高可操作的请求数量来拉取请求来处理,这样可以使系统在高峰期也不会挂掉,等高峰一过就会消费多积压的消息
MQ的优点和缺点
-
系统可用性降低
MQ一旦故障,其他系统就没法收到消息,导致整个系统无法运转了
-
系统复杂性提高
需要考虑更多可能出现的问题,MQ消息丢了,MQ消息顺序出问题了,MQ积压大量消息。
-
一致性问题
系统ABC执行成功了,但是系统D执行失败了,但是返回的结果却是成功,实际后台数据是有问题的。
Kafka、ActiveMQ、RabbitMQ、RocketMQ之间的差异
特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
---|---|---|---|---|
单机吞吐量 | 万级吞吐量,比RocketMQ和Kafka低一个等级 | 万级,吞吐量比RocketMQ和Kafka低一个等级 | 10万级 | 10万级 |
topic数量对吞吐量的影响 | topic可以达到成百上千个,吞吐量有小幅度下降 | topic从几十到几百个,吞吐量会大幅度下降 | ||
时效性 | ms级 | 微妙级 | ms级 | ms级 |
可用性 | 高,基于主从架构实现高可用 | 高,基于主从架构实现高可用 | 非常高,分布式架构 | 非常高,分布式架构 |
消息可靠性 | 较低的概率丢失数据 | 经过参数配置可以达到0丢失 | 经过参数配置可以达到0消息丢失 | |
功能支持 | MQ领域的功能极其完备 | 高并发性能,延时低 | 扩展性好 | 功能简单,支持简单的MQ功能,大数据领域使用较多 |
优劣势总结 | 非常成熟,功能强大,偶尔会有数据丢失,官方维护较少 | 性能极其好,延时低,有开源管理界面,社区活跃 | 接口简单,性能好,吞吐量大,文档简单 | 仅仅提供较少的核心功能,但是提供超高的吞吐量和ms级的延迟,唯一劣势可能会重复消费消息,但是这点影响在大数据处理中可以忽略不计 |
所以对于一般小公司而言,可以考虑使用RabbitMQ或者RocketMQ都可以,如果对自己实力绝对有自信,那么推荐使用RocketMQ,因为阿里提供了源码,可以定制适合自己的MQ。
如何保证消息队列的高可用
rabbitMQ:
-
单机模式
-
普通集群模式
多个机器来提供队列服务,提高了吞吐量,由于一个queue只会在集群中的某一个机器上存在,所以也有两个主要缺点:可能会在rabbitMQ集群内部产生大量的数据传输;可用性几乎没有保障,如果存储queue的机器宕机了,那就没法消费了
-
镜像集群模式
每个queue的全部数据会在集群中的每个节点都会存在,任何节点宕机了都不会对消息产生影响,所以消费者任何节点消费都没有问题。
如何保证消息不被重复消费?
解决方案:
保证MQ重复消费的幂等性,一条消息重复出现两次,但数据库中只有一条数据,无论请求多少次都只有一条数据。
每次消费一条消息后,对消息记录一下,比如存到表里或者内存set中来记录一下,每次消费前查询一下有没有记录过,有记录说明之前已经被消费过了,就不用再往下走了。
保证消息的可靠性传输(如何处理消息丢失的问题)(RabbitMQ)
-
生产者写消息的过程中,没有正常的存储到RabbitMQ中
可以捕获异常后再继续发送消息,但是方法是阻塞的,效率低,不建议使用。
将channel设置为confirm模式,在消息发送完后,无论成功或失败都会有对应的回调方法来执行后续操作,不会阻塞请求。
-
RabbitMQ接收到消息后先暂存到内存中,还没来得及消费,RabbitMQ挂掉了
创建queue的时候将其设置为持久化的,同时在发送消息的时候讲消息的deliveryMode设置为2来将消息设置为持久化,必须同时设置这两个持久化才行。哪怕RabbitMQ挂掉了当它重启后才不会丢失消息
-
消费者消费到了消息,但是还没来得及处理自己挂掉了
RabbitMQ默认打开了autoAck的机制,我们首先关闭autoAck机制,每次消费处理完一个消息后手动发送ack给MQ
保证消息的顺序性
如果有三条数据想通过三个消费者按照顺序来插入到数据库中,但是由于三个消费者执行顺序的不同导致入库的顺序有误。
对于RabbitMQ而言,解决办法是,每个queue(队列)对应一个消费者,将需要执行的操作放入对应的队列中让消费者按顺序去消费。
消息队列积压过多消息(消费端出问题了)
假如有三个消费者,一个消费者一秒处理1000个请求,三个消费者一秒3000个请求,一分钟18w请求,一小时就处理1000w+个请求。如果积压了千万条请求,那就得花大概一小时来处理请求。