rocketmq借鉴了kafka的思想,具有后发的优势。相对于kafka rocketmq做了一些调整,性能可能相对于kafka略逊一筹不过功能以及可用性有了很大的提升是专为业务而设计的MQ经历过阿里双11的验证。
kafka相关使用可以看上篇博客。
RocketMQ是一款纯java开发的分布式队列模型的开源消息中间件,支持事务消息,严格有序的顺序消息,批量消息,延时消息,消息回溯等等,具有高性能、高实时、分布式的特性。
rocketmq中一条消息没有消费成功下面的消息是不能消费的,在broker中是有锁的保证了消息的严格有序。
其实只有拉模型。推模型实际是拉模型模拟的,一次拉取一批消息然后推送到消费者线程。
支持亿级消息堆积能力,堆积了很多消息依然可以低延迟写入
也就是说在rocketmq的消息至少会被消费一次,rocketmq是允许重复消费的我们用rocketmq要自己做好消息的幂等性处理。
不过这种方案只能保证在生产者方服务器的分布式事务,先发送半事务消息,发送生产方服务器事务成功了才发送消息,不过消费者服务器如果回滚了是无法通知生产者服务器的需要额外的方案来处理,所以分布式事务目前主流的方案一般还是用seata来处理。
本地系统调用第三方系统时根据失败次数的递增,重试调用时间也递增超过指定时间没有重试成功,再把消息丢到死信队列。
一个topic支持broker端的tag过滤使一个topic可以支持不同的使用场景的消费者消费。
消息消费后不会删除,消息会持久化到磁盘上。
命名服务器,和zookeeper作用是一样的。不过name server是一个无状态的节点,集群中的name server服务器是不交互的。
它是rocketmq的服务注册中心,先启动nameserver后启动broker,broker会注册到name server集群中的每一个name server上,每一个name server和broker会保持心跳连接,默认每隔30sbroker会向name server上报topic信息,topic:broker列表信息。producer和consumer也会与name server 保持连接发送消息和消费消息时会根据自身的topic找到name server中topic找到对应的broker信息。
就是rocketmq的实体,存储消息相关的元数据,包括用户组、消费进度偏移量、队列信息等等。
broker又分为主从,master节点和slave节点。默认master节点既可以写也可以读,slave节点只可以读不可以写,不过在master节点宕机或者压力过大可以直接使用slave节点,默认4.7以下版本不支持主从切换,最新的RocketMq版本是支持的。
部署简单只有一个master的broker服务器,不过broker宕机会使消息队列不可用
单个 Master 宕机或重启维
护对应用无影响,缺点是单台机器宕机期间,该机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受影响
每个 Master 配置一个 Slave,所以有多对 Master-Slave ,消息采用同步复制方式,主备都写成功才返回成功,这种方式优点是数据与服务都没有单点问题,Master 宕机时消息无延迟,服务与数据的可用性非常高,缺点是性能相对异步复制方式略低,发送消息的延迟会略高。优势是tps很高。
每个 Master 配置一个 Slave,所以有多对 Master-Slave,消息采用异步复制方式,消息写到主broker成功了就返回成功,主备之间有毫秒级消息延迟,这种方式优点是消息丢失的非常少,且消息实时性不会受影响,Master 宕机后消费者可以继续从 Slave 消费,中间的过程对用户应用程序透明,不需要人工干预,性能同多 Master 方式几乎一样,缺点是 Master 宕机时还没有来得及复制到slave在磁盘损坏情况下会丢失极少量消息。优势是消息的安全性非常高。要求消息一定可以丢失要用这种。
每个Broker与Name Server集群中的所有节点建立长连接,定时(每隔30s)注册Topic信息到所有Name Server,Name Server定时(每隔10s)扫描所有存活broker的连接,如果Name Server超过2分钟没有收到心跳,则Name Server断开与Broker的连接。
消息生产者,负责生产并发送消息到指定topic的broker。
发送数据后接收到响应才发送下一条。
发送数据后无需接收到响应就可以发送下一条。
类似kafka的发送并忘记只负责发送不等待broker回应,最不安全tps最高
与broker类似,它也会与name server建立心跳连接。
消息订阅者,负责从指定topic的broker中接收并消费消息。
分为推和拉两种模式,推模型是拉模式模拟的。
消费消息时通过 Consumer Group 实现了将消息分发到多个消费者服务器实例, 每个消息只会被同一个消费者组的消费者消费一次,多个组可以消费同一个消息,消费者组是用group id 来命名区分的。比如某个 Topic有9条消息,其中一个 Consumer Group 有3个实例(3个进程或3台机器),那么每个实例将均摊3条消息,这也意味着我们可以很方便的通过加机器来实现水平扩展。
与broker类似,它也会与name server建立心跳连接。
消息就是要传输的信息,消息必须有一个主题信息(topic),一条消息可用拥有一个可选的tag和额外的键值对,可选的tag类似于二级主题,它们可以作为一个业务key在broker上查找到此消息
Topic是消息的第一级类型,一条消息必有要有一个topic
Tag可以看做一个子主题,是消息的第二级类型为用户提供了额外的灵活性。tag可以把主题分为多个类别比如以订单为topic的消息可以分为订单创建的tag消息和订单完成的tag消息,这样可以以topic+tag为维度的去生产以及消费消息,一条消息是可以没有tag的
Message Queue 相当于kafka的partition的概念。在rocketmq中将topic分为一个或者多个子主题也就是消息队列。一个主题可以分布在多个rocketmq broker上,每个子主题有一个message queue。
默认情况下是集群消费,该模式下一个消费者集群共同消费一个主题的多个队列,一个队列只会被一个消费者消费,如果消费者宕机分组内的其他消费者会再均衡替换宕机的消费者继续消费
广播消费是发给消费者组中的每一个消费者消费。
顺序消费表示消息消费的顺序同生产者为每个消息队列发送的顺序一致。
并行消费不保证消息顺序,消费的最大并行数量受每个消费者客户端指定的线程池限制
RocketMQ追求消息发送的高吞吐量,RocketMQ消息存储文件设计成文件组的概念,组内单个文件大小固定,方便引入内存映射机制。所有主题的消息存储基于顺序写,提升写性能,同时为了兼顾消息消费与消息查找,引入了消息消费队列文件与索引文件。
通过内存映射机制、零拷贝技术使rocketmq性能非常高
rocketmq追求消息存储的高性能,引入内存映射机制,所有主题的消息顺序存储在同一个文件中,同时为了避免消息无限在消息存储服务器中累积,引入了消息文件过期机制与文件存储空间报警机制,这是它与kafka最大的区别。
kafka的数据存储是每个partition一个log文件,分区的数量达到一定的阈值当同时写入的时候它的顺序写会变成随机写性能会变低。而rocketmq是所有的topic下面的消息队列公用一个commit log无论多少主题多少消息队列都写到同一个commit log文件中保证同时只有一个文件在顺序写。消息写入到commitlog后由broker中的一个线程拉取消息在commitlog中的索引位置到消费者队列,而消费者组就是基于消费者队列找到commitlog中的消息位置来消费。
写到内存的同时写入磁盘
写到内存后由另一个线程异步写入磁盘,broker宕机内存清掉有可能数据丢失。
rocketmq无论生产者发送消息到broker还是消费者从broker消费消息都不存在幂等性设计,幂等性问题需要用户自己处理。所以我们在使用rocketmq做业务处理时要在代码中做好幂等性处理。
百分之百高可靠一条都不能丢用同步复制同步刷盘,常规的业务场景通常使用同步复制异步刷盘。异步刷盘的性能相对好一些。
rocketmq通过消息消费确认机制(ACK)确保消息至少消费一次,但是有重复消费的可能。
消费端已经消费的消息如果需要重新消费,rocketmq支持按时间回溯消息,可以向前或者向后回溯消息。
rocketmq存储使用的是内存映射机制,在物理布局上为多个大小相等的文件组成逻辑文件组,可以无线循环使用,rocketmq支持亿级的消息堆积,默认消息保留3天,3天后不论消息是否消费成功会直接删除。
消息到broker后延迟指定时间后才能被消费,rocketmq支持18个等级的延迟消息,用rocketmq商业版本可以使用任意时间的延迟消息。
消息重试是指消息消费时如果异常了broker可以重新投递。