RabbitMQ

erlang开发,对消息堆积的支持并不好,当大量消息积压的时候,会导致RabbitMQ的性能急剧下降。每秒钟可以处理几万到十几万条消息。

RocketMQ

Java开发,面向​​互联网集群化​​,功能丰富,对在线业务的响应时延做了很多的优化,大多数情况下可以做到毫秒级的响应,每秒钟大概能处理几十万条消息。

Kafka

Scala开发,面向​​日志​​,功能丰富,性能最高。当你的业务场景中,每秒钟消息数量没有那么多的时候,Kafka 的时延反而会比较高。所以,Kafka 不太适合在线业务场景。

ActiveMQ

Java开发,简单,稳定,性能不如前面三个。小项目可以选择。


RocketMq组成部分有哪些?

Nameserver

无状态,动态列表;这也是和zookeeper的重要区别之一。zookeeper是有状态的。

Producer

消息生产者,负责发消息到Broker。

Broker

就是MQ本身,负责收发消息、持久化消息等。

Consumer

消息消费者,负责从Broker上拉取消息进行消费,消费完进行ack。


RocketMq消费模式有几种?

集群消费

一条消息只会被同Group中的一个Consumer消费。

多个Group同时消费一个Topic时,每个Group都会有一个Consumer消费到数据

广播消费

消息将对一个Consumer Group下的各个Consumer实例都消费一遍。即使这些Consumber属于同一个Consumer Group,消息也会被Consumer Group中的每个Consumer都消费一次。


消费重复消费如何解决?

出现原因:正常情况下在在consumer真正消费完消息后应该发送ack,通知broker该消息已正常消费,从queue中删除。当ack因为网络原因无法发送到broker,broker会认为词条消息没有被消费,此后会开启消息重投机制把消息再次投递到consumer。

消费模式:在CLUSTERING模式下,消息在broker中会保证相同group的consumer消费一次,但是针对不同的group的consumer会推送多次。

解决方案

a.数据库表:处理消息前,使用消息主键在表中带有约束的字段中insert

b.map:单机时可以使用map做限制,消费时查询当前消息id是不是已经存在

c.redis:使用分布式锁


rocketmq如何保证消息的顺序消费?

首先多个queue只能保证单个queue里的顺序,queue是典型的FIFO,天然顺序。多个queue同时消费是无法绝对保证消息的有序性的。

可以使用同一个topic,同一个QUEUE,发消息的时候一个线程去发送消息,消费的时候一个线程去消费一个queue里的消息。


RocketMQ如何保证消息不丢失?

producer端

采用send()同步发消息,发送结果是同步感知的。发送失败后可以重试,设置重试次数。默认3次。


broker端

修改刷盘策略为同步刷盘。默认情况下是异步刷盘的。

集群部署


Consumer端

完全消费正常后在进行手动ack确认。


RocketMq如何实现分布式事务?

1、生产者向MQ服务器发送half消息。

2、half消息发送成功后,MQ服务器返回确认消息给生产者。

3、生产者开始执行本地事务。

4、根据本地事务执行的结果(UNKNOW、commit、rollback)向MQ server发送提交或回滚消息。

5、如果错过了(可能因为网络异常、生产者突然宕机等导致的异常情况)提交/回滚消息,则MQ服务器将向同一组中的每个生产者发送回查消息以获取事务状态。

6、回查生产者本地事务状态。

7、生产者根据本地事务状态发送提交/回滚消息。

8、MQ服务器将丢弃的回滚的消息,但已提交(进行过二次确认的half消息)的消息将投递给消费者进行消费。

​Half Message​​:预处理消息,当broker收到此类消息后,会存储到​​RMQ_SYS_TRANS_HALF_TOPIC​​的消息消费队列中

​检查事务状态​​:Broker会开启一个定时任务,消费​​RMQ_SYS_TRANS_HALF_TOPIC​​队列中的消息,每次执行任务会向消息发送者确认事务执行状态(提交、回滚、未知),如果是未知,Broker会定时去回调在重新检查。

超时:如果超过回查次数,默认回滚消息。

也就是他并未真正进入Topic的queue,而是用了临时queue来放所谓的​​half message​​,等提交事务后才会真正的将half message转移到topic下的queue。


RocketMQ的消息堆积如何处理?

​1、如果可以添加消费者解决,就添加消费者的数据量

2、如果出现了queue,但是消费者多的情况。可以使用准备一个临时的topic,同时创建一些queue,在临时创建一个消费者来把这些消息转移到topic中,让消费者消费。