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消息)的消息将投递给消费者进行消费。
超时:如果超过回查次数,默认回滚消息。 也就是他并未真正进入Topic的queue,而是用了临时queue来放所谓的 1、如果可以添加消费者解决,就添加消费者的数据量 2、如果出现了queue,但是消费者多的情况。可以使用准备一个临时的topic,同时创建一些queue,在临时创建一个消费者来把这些消息转移到topic中,让消费者消费。Half Message
:预处理消息,当broker收到此类消息后,会存储到RMQ_SYS_TRANS_HALF_TOPIC
的消息消费队列中检查事务状态
:Broker会开启一个定时任务,消费RMQ_SYS_TRANS_HALF_TOPIC
队列中的消息,每次执行任务会向消息发送者确认事务执行状态(提交、回滚、未知),如果是未知,Broker会定时去回调在重新检查。half message
,等提交事务后才会真正的将half message转移到topic下的queue。RocketMQ的消息堆积如何处理?