RocketMQ是阿里巴巴于2016年开源的消息中间件,使用JAVA语言开发。

基本概念
RocketMQ各部分角色介绍:

RocketMQ主要由四部分组成:

  • Producer:消息生产者,主要负责消息的生产,一般由业务系统负责消息的生产,一个消息生产者会把业务应用系统产生的消息发送到Broker服务器中存储。RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送,同步和异步方式均需要Broker返回确认消息。单向发送不需要。
  • Consumer:消息消费者,负责消费消息,一般是后台系统负责异步消费,一个消息消费者会从Broker中拉取消息,并将其提供给应用程序,从用户应用角度而言,提供了两种消费方式:拉取式消费和推动式消费。
    拉取式消费:Consumer消费的一种类型,应用通常主动调用Consumer的拉消息方法从Broker服务器拉取消息,主动权由应用控制,一旦获取了批量消息,应用就会启动主动消费过程。
    推动式消费:Consumer消费的一种类型,该模式下Broker收到数据后会主动推送给消费端,该消费模式一般实时性较高。
  • Broker:消息中转角色,负责存储,转发消息,Broker在RocketMQ系统中从生产者中接收消息并进行存储,同时为消费者拉取消息做好准备。Broker也存储消息相关的元数据,包括消费者组、消费进度偏移量,主题、队列等。
  • NameServer:名称服务充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Namesrv实例组成集群,但相互独立,没有信息交换。
Topic

Topic表示一类消息的集合,每个Topic包含若干条消息,每条消息只能属于一个Topic,是RocketMQ进行消息订阅的基本单位。

Message Queue

有了Topic以后,还需要解决性能问题,如果一个Topic要发送或者接收的数据量非常大,需要能增加并行处理的机器来提高处理速度,这时候可以根据需求设置一个或者多个Message Queue,Message Queue类似于分区,将Topic中的消息分配在这些Message Queue中,当Topic有了多个Message Queue后,生产者可以把消息可以并行地往这些Message Queue发送,消费者也可以并行地从多个Message Queue读取消息并消费。

Producer Group

生产者组,同一类消息生产者的集合,这类生产者发送同一类消息,并且发送的逻辑都是一样的,如果发送的是事务消息,并且原始生产者在发送之后崩溃了,则Broker服务器会联系同一生产者组的其他生产者实例以提交或者回溯消息。

Consumer Group

消费者组,同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致。
消费者组使得在消息消费方面,实现负载均衡和容错变得非常容易。
要注意的是,同一消费者组的消费者实例必须订阅完全相同的topic,RocketMQ支持两种消息模式:集群消费和广播消费。

  • 集群消费:同一消费者组的消费者实例平均分摊消息。
  • 广播消费:同一消费者组的消费者实例都接收全量消息。
普通顺序消息

在普通顺序消费模式下,消费者通过同一消息队列收到的消息是顺序的,不同消息队列收到的消息可能是无序的。

严格顺序消息

消费者收到的所有消息都是顺序的。

消息

消息是消息系统所传输的信息数据的物理载体,生产和消费数据的最小单位,每条消息都必须属于一个主题,RocketMQ中的每个消息都拥有一个唯一的Message ID,并且可以携带具有业务标志的Key,系统提供了通过Message Id 或者 Key 查询消息的功能。

标签Tag

为消息设置标志,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不同的业务目的在同一主题下设置不同的标签,标签能够有效保持代码的清晰度和连贯性,并且优化RocketMQ提供的查询功能,消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。

特性

介绍RocketMQ实现的功能特性。

订阅与发布

消息发布是指消息生产者向某个topic发送消息。
消息的订阅是指消息消费者关注了某个Topic中带有某些tag的消息,进而从该tag消费消息。

消息顺序

消息消费是指一类消息消费时,能够按照发送的顺序来消费,例如一个订单产生了三条消息:订单创建消息、订单付款消息、订单完成消息。消费时要严格按照这个顺序来消费消息才有意义。但是订单之间是可以并行消费的,没有严格顺序,比如订单1和订单2各自产生了这个三条消息,订单1的订单付款消息无需在订单2的订单创建消息之后消费。

顺序消息可以分为全局顺序消息和分区顺序消息:

  • 全局顺序消息:对于一个指定的Topic,所有消息都按照先进先出(FIFO)的顺序进行发布和消费消费。适用于性能要求不高,所有的消息严格按照 FIFO 原则进行消息发布和消费的场景。
  • 分区顺序消息:对于一个Topic,所有消息根据sharding key 进行区块分区。同一分区里面的消息严格按照FIFO顺序进行发布和消费。Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key 是完全不同的概念。分区就是上面基本概念中的Message Queue。适用于性能要求高,以 sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景。
消息过滤

RocketMQ的消费者可以根据Tag进行消息的过滤,也支持自定义的过滤,消息的过滤目前是在Broker端实现的,优点是可以减少传输到Consumer的无用消息,因为在Broker端就已经过滤掉了,传到Consumer的都是关注的消息。缺点是增加了Broker的负担,因为要进行过滤,而且实现也复杂。

消息可靠性

RocketMQ支持消息的高可靠,影响消息可靠性的几种情况:

  • Broker非正常关闭。
  • Broker异常宕机。
  • 操作系统宕机。
  • 机器掉电,但是能立即回复供电情况。
  • 机器无法开机,(可能是cpu、主板、内存等关键设备损坏)。
  • 磁盘设备损坏。

前面四种都属于硬件资源可立即恢复情况,RocketMQ在这四种情况下能保证消息不丢,或者丢失少量数据(依赖刷盘方式是同步还是异步)。如果刷盘方式是同步的话,可以保证数据不丢,如果是异步的话,可能会丢失少量数据。

后面两种情况属于单点故障,并且无法恢复,一旦发生,在此单点上的消息全部丢失。RocketMQ在这两种情况下,通过主从集群异步复制方式可以保证消息99%不丢失,如果通过主从集群同步复制方式可以保证数据不丢失,完全避免单点故障。但是同步复制势必会影响性能,适合对消息可靠性要求极高的场合,例如与Money相关的应用。注:RocketMQ从3.0版本开始支持同步双写。

至少投递一次

指Broker至少把每个消息必须投递一次给Consumer。Consumer先Pull消息到本地,消费完成后,才向服务器返回ack,如果没有消费一定不会ack消息,所以RocketMQ可以很好的支持此特性。

事务消息

RocketMQ事务消息是指本地事务和发送消息操作可以定义在一个事务中,要么同时成功,要么同时失败。RocketMQ的事务消息提供类似 X/Open XA 的分布事务功能,通过事务消息能达到分布式事务的最终一致。

定时消息

定时消息(延时队列)是指消息发送到Broker后,不会立即被消费,而是进入Broker的延时队列里面,等到特定的时间再投递到指定的Topic中。
Broker有配置项messageDelayLevel,默认值为1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h”,18个level。可以配置自定义messageDelayLevel。
messageDelayLevel是broker的属性,不属于某个topic。发消息时,设置delayLevel等级即可:msg.setDelayLevel(level)。

Level有以下三种情况:
level = 0 :非延时消息。
1<=level<=maxLevel,消息延迟特定时间,例如level1,延迟1s
level > maxLevel,则level
maxLevel,例如level==20,延迟2h

定时消息会暂存在名为SCHEDULE_TOPIC_XXXX的topic中,并根据delayTimeLevel存入特定的queue,queueId = delayTimeLevel – 1,即一个queue只存相同延迟的消息,保证具有相同发送延迟的消息能够顺序消费。broker会调度地消费SCHEDULE_TOPIC_XXXX,将消息写入真实的topic。

需要注意的是,定时消息会在第一次写入和调度写入真实topic时都会计数,因此发送数量、tps都会变高。也就是一个延时消息在Broker中会被计数两次。

死信队列

死信队列用于处理无法被正常消费的消息。当一条消息初次消费失败(没有返回ack),消息队列会自动进行消息重试;达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息,此时,消息队列 不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中。死信队列与消费者对应。

RocketMQ将这种正常情况下无法被消费的消息称为死信消息(Dead-Letter Message),将存储死信消息的特殊队列称为死信队列(Dead-Letter Queue)。在RocketMQ中,可以通过使用console控制台对死信队列中的消息进行重发来使得消费者实例再次进行消费。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐