本文转载自 阿里中间件团队博客的文章十分钟入门RocketMQ

本文首先引出消息中间件通常须要解决哪些问题,在解决这些问题当中会遇到什么艰难,Apache RocketMQ作为阿里开源的一款高性能、高吞吐量的分布式消息中间件否能够解决,标准中如何定义这些问题。而后本文将介绍RocketMQ的架构设计,以期让读者疾速理解RocketMQ。

消息中间件须要解决哪些问题?

Publish/Subscribe

公布订阅是消息中间件的最基本功能,也是绝对于传统RPC通信而言。在此不再详述。

Message Priority

标准中形容的优先级是指在一个音讯队列中,每条音讯都有不同的优先级,个别用整数来形容,优先级高的音讯先投递,如果音讯齐全在一个内存队列中,那么在投递前能够依照优先级排序,令优先级高的先投递。
因为RocketMQ所有音讯都是长久化的,所以如果依照优先级来排序,开销会十分大,因而RocketMQ没有特意反对音讯优先级,然而能够通过变通的形式实现相似性能,即独自配置一个优先级高的队列,和一个一般优先级的队列, 将不同优先级发送到不同队列即可。

对于优先级问题,能够演绎为2类:

  1. 只有达到优先级目标即可,不是严格意义上的优先级,通常将优先级划分为高、中、低,或者再多几个级别。每个优先级能够用不同的topic示意,发消息时,指定不同的topic来示意优先级,这种形式能够解决绝大部分的优先级问题,然而对业务的优先级精确性做了斗争。
  2. 严格的优先级,优先级用整数示意,例如0 ~ 65535,这种优先级问题个别应用不同topic解决就十分不适合。如果要让MQ解决此问题,会对MQ的性能造成十分大的影响。这里要确保一点,业务上是否的确须要这种严格的优先级,如果将优先级压缩成几个,对业务的影响有多大?

Message Order

音讯有序指的是一类音讯生产时,能依照发送的程序来生产。例如:一个订单产生了3条音讯,别离是订单创立,订单付款,订单实现。生产时,要依照这个程序生产能力有意义。然而同时订单之间是能够并行生产的。
RocketMQ能够严格的保障音讯有序。

Message Filter

Broker端音讯过滤

在Broker中,依照Consumer的要求做过滤,长处是缩小了对于Consumer无用音讯的网络传输。
毛病是减少了Broker的累赘,实现绝对简单。

  1. 淘宝Notify反对多种过滤形式,蕴含间接依照音讯类型过滤,灵便的语法表达式过滤,简直能够满足最刻薄的过滤需要。
  2. 淘宝RocketMQ反对依照简略的Message Tag过滤,也反对依照Message Header、body进行过滤。
  3. CORBA Notification标准中也反对灵便的语法表达式过滤。

Consumer端音讯过滤

这种过滤形式可由利用齐全自定义实现,然而毛病是很多无用的音讯要传输到Consumer端。

Message Persistence

消息中间件通常采纳的几种长久化形式:

  1. 长久化到数据库,例如Mysql。
  2. 长久化到KV存储,例如levelDB、伯克利DB等KV存储系统。
  3. 文件记录模式长久化,例如Kafka,RocketMQ
  4. 对内存数据做一个长久化镜像,例如beanstalkd,VisiNotify
  5. (1)、(2)、(3)三种长久化形式都具备将内存队列Buffer进行扩大的能力,(4)只是一个内存的镜像,作用是当Broker挂掉重启后依然能将之前内存的数据恢复进去。

JMS与CORBA Notification标准没有明确阐明如何长久化,然而长久化局部的性能间接决定了整个消息中间件的性能。

RocketMQ充分利用Linux文件系统内存cache来进步性能。

Message Reliablity

影响音讯可靠性的几种状况:

  1. Broker失常敞开
  2. Broker异样Crash
  3. OS Crash
  4. 机器掉电,然而能立刻复原供电状况。
  5. 机器无奈开机(可能是cpu、主板、内存等关键设备损坏)
  6. 磁盘设施损坏。

(1)、(2)、(3)、(4)四种状况都属于硬件资源可立刻复原状况,RocketMQ在这四种状况下能保障音讯不丢,或者失落大量数据(依赖刷盘形式是同步还是异步)。

(5)、(6)属于单点故障,且无奈复原,一旦产生,在此单点上的音讯全副失落。RocketMQ在这两种状况下,通过异步复制,可保障99%的音讯不丢,然而依然会有极少量的音讯可能失落。通过同步双写技术能够完全避免单点,同步双写势必会影响性能,适宜对音讯可靠性要求极高的场合,例如与Money相干的利用。

RocketMQ从3.0版本开始反对同步双写。

Low Latency Messaging

在音讯不沉积状况下,音讯达到Broker后,能立即达到Consumer。
RocketMQ应用长轮询Pull形式,可保障音讯十分实时,音讯实时性不低于Push。

At least Once

是指每个音讯必须投递一次。
RocketMQ Consumer先pull音讯到本地,生产实现后,才向服务器返回ack,如果没有生产肯定不会ack音讯,所以RocketMQ能够很好的反对此个性。

Exactly Only Once

  1. 发送音讯阶段,不容许发送反复的音讯。
  2. 生产音讯阶段,不容许生产反复的音讯。

只有以上两个条件都满足状况下,能力认为音讯是“Exactly Only Once”,而要实现以上两点,在分布式系统环境下,不可避免要产生微小的开销。所以RocketMQ为了谋求高性能,并不保障此个性,要求在业务上进行去重,也就是说生产音讯要做到幂等性。RocketMQ尽管不能严格保障不反复,然而失常状况下很少会呈现反复发送、生产状况,只有网络异样,Consumer启停等异常情况下会呈现音讯反复。

Broker的Buffer满了怎么办?

Broker的Buffer通常指的是Broker中一个队列的内存Buffer大小,这类Buffer通常大小无限,如果Buffer满了当前怎么办?
上面是CORBA Notification标准中解决形式:

  1. RejectNewEvents 回绝新来的音讯,向Producer返回RejectNewEvents错误码。
  2. 依照特定策略抛弃已有音讯

    • AnyOrder - Any event may be discarded on overflow. This is the default setting for this property.
    • FifoOrder - The first event received will be the first discarded.
    • LifoOrder - The last event received will be the first discarded.
    • PriorityOrder - Events should be discarded in priority order, such that lower priority events will be discarded before higher priority events.
    • DeadlineOrder - Events should be discarded in the order of shortest expiry deadline first.

RocketMQ没有内存Buffer概念,RocketMQ的队列都是长久化磁盘,数据定期革除。

对于此问题的解决思路,RocketMQ同其余MQ有十分显著的区别,RocketMQ的内存Buffer形象成一个有限长度的队列,不论有多少数据进来都能装得下,这个有限是有前提的,Broker会定期删除过期的数据,例如Broker只保留3天的音讯,那么这个Buffer尽管长度有限,然而3天前的数据会被从队尾删除。

此问题的实质起因是网络调用存在不确定性,即既不胜利也不失败的第三种状态,所以才产生了音讯重复性问题。

回溯生产

回溯生产是指Consumer曾经生产胜利的音讯,因为业务上需要须要从新生产,要反对此性能,Broker在向Consumer投递胜利音讯后,音讯依然须要保留。并且从新生产个别是依照工夫维度,例如因为Consumer系统故障,复原后须要从新生产1小时前的数据,那么Broker要提供一种机制,能够依照工夫维度来回退生产进度。
RocketMQ反对依照工夫回溯生产,工夫维度准确到毫秒,能够向前回溯,也能够向后回溯。

音讯沉积

消息中间件的次要性能是异步解耦,还有个重要性能是挡住前端的数据洪峰,保障后端系统的稳定性,这就要求消息中间件具备肯定的音讯沉积能力,音讯沉积分以下两种状况:

  1. 音讯沉积在内存Buffer,一旦超过内存Buffer,能够依据肯定的抛弃策略来抛弃音讯,如CORBA Notification标准中形容。适宜能容忍抛弃音讯的业务,这种状况音讯的沉积能力次要在于内存Buffer大小,而且音讯沉积后,性能降落不会太大,因为内存中数据多少对于对外提供的拜访能力影响无限。
  2. 音讯沉积到长久化存储系统中,例如DB,KV存储,文件记录模式。 当音讯不能在内存Cache命中时,要不可避免的拜访磁盘,会产生大量读IO,读IO的吞吐量间接决定了音讯沉积后的拜访能力。

评估音讯沉积能力次要有以下四点:

  1. 音讯能沉积多少条,多少字节?即音讯的沉积容量。
  2. 音讯沉积后,发消息的吞吐量大小,是否会受沉积影响?
  3. 音讯沉积后,失常生产的Consumer是否会受影响?
  4. 音讯沉积后,拜访沉积在磁盘的音讯时,吞吐量有多大?

分布式事务

已知的几个分布式事务标准,如XA,JTA等。其中XA标准被各大数据库厂商广泛支持,如Oracle,Mysql等。其中XA的TM实现佼佼者如Oracle Tuxedo,在金融、电信等畛域被广泛应用。

分布式事务波及到两阶段提交问题,在数据存储方面的方面必然须要KV存储的反对,因为第二阶段的提交回滚须要批改音讯状态,肯定波及到依据Key去查找Message的动作。RocketMQ在第二阶段绕过了依据Key去查找Message的问题,采纳第一阶段发送Prepared音讯时,拿到了音讯的Offset,第二阶段通过Offset去拜访音讯,并批改状态,Offset就是数据的地址。

RocketMQ这种实现事务形式,没有通过KV存储做,而是通过Offset形式,存在一个显著缺点,即通过Offset更改数据,会令零碎的脏页过多,须要特地关注。

定时音讯

定时音讯是指音讯发到Broker后,不能立即被Consumer生产,要到特定的工夫点或者期待特定的工夫后能力被生产。
如果要反对任意的工夫精度,在Broker层面,必须要做音讯排序,如果再波及到长久化,那么音讯排序要不可避免的产生微小性能开销。
RocketMQ反对定时音讯,然而不反对任意工夫精度,反对特定的level,例如定时5s,10s,1m等。

音讯重试

Consumer生产音讯失败后,要提供一种重试机制,令音讯再生产一次。Consumer生产音讯失败通常能够认为有以下几种状况:

  1. 因为音讯自身的起因,例如反序列化失败,音讯数据自身无奈解决(例如话费充值,以后音讯的手机号被登记,无奈充值)等。这种谬误通常须要跳过这条音讯,再生产其余音讯,而这条失败的音讯即便立即重试生产,99%也不胜利,所以最好提供一种定时重试机制,即过10s秒后再重试。
  2. 因为依赖的上游应用服务不可用,例如db连贯不可用,外零碎网络不可达等。遇到这种谬误,即便跳过以后失败的音讯,生产其余音讯同样也会报错。这种状况倡议利用sleep 30s,再生产下一条音讯,这样能够加重Broker重试音讯的压力。

RocketMQ Overview

RocketMQ是否解决了上述消息中间件面临的问题,接下来让咱们一探到底。

RocketMQ 是什么?

上图是一个典型的消息中间件收发音讯的模型,RocketMQ也是这样的设计,简略说来,RocketMQ具备以下特点:

  • 是一个队列模型的消息中间件,具备高性能、高牢靠、高实时、分布式特点。
  • Producer、Consumer、队列都能够分布式。
  • Producer向一些队列轮流发送音讯,队列汇合称为Topic,Consumer如果做播送生产,则一个consumer实例生产这个Topic对应的所有队列,如果做集群生产,则多个Consumer实例均匀生产这个topic对应的队列汇合。
  • 可能保障严格的音讯程序
  • 提供丰盛的音讯拉取模式
  • 高效的订阅者程度扩大能力
  • 实时的音讯订阅机制
  • 亿级音讯沉积能力
  • 较少的依赖

RocketMQ 物理部署构造

如上图所示, RocketMQ的部署构造有以下特点:

  • Name Server是一个简直无状态节点,可集群部署,节点之间无任何信息同步。
  • Broker部署绝对简单,Broker分为Master与Slave,一个Master能够对应多个Slave,然而一个Slave只能对应一个Master,Master与Slave的对应关系通过指定雷同的BrokerName,不同的BrokerId来定义,BrokerId为0示意Master,非0示意Slave。Master也能够部署多个。每个Broker与Name Server集群中的所有节点建设长连贯,定时注册Topic信息到所有Name Server。
  • Producer与Name Server集群中的其中一个节点(随机抉择)建设长连贯,定期从Name Server取Topic路由信息,并向提供Topic服务的Master建设长连贯,且定时向Master发送心跳。Producer齐全无状态,可集群部署。
  • Consumer与Name Server集群中的其中一个节点(随机抉择)建设长连贯,定期从Name Server取Topic路由信息,并向提供Topic服务的Master、Slave建设长连贯,且定时向Master、Slave发送心跳。Consumer既能够从Master订阅音讯,也能够从Slave订阅音讯,订阅规定由Broker配置决定。

RocketMQ 逻辑部署构造

如上图所示,RocketMQ的逻辑部署构造有Producer和Consumer两个特点。

Producer Group

用来示意一个发送音讯利用,一个Producer Group下蕴含多个Producer实例,能够是多台机器,也能够是一台机器的多个过程,或者一个过程的多个Producer对象。一个Producer Group能够发送多个Topic音讯,Producer Group作用如下:

  1. 标识一类Producer
  2. 能够通过运维工具查问这个发送音讯利用下有多个Producer实例
  3. 发送分布式事务音讯时,如果Producer中途意外宕机,Broker会被动回调Producer Group内的任意一台机器来确认事务状态。

Consumer Group

用来示意一个生产音讯利用,一个Consumer Group下蕴含多个Consumer实例,能够是多台机器,也能够是多个过程,或者是一个过程的多个Consumer对象。一个Consumer Group下的多个Consumer以均摊形式生产音讯,如果设置为播送形式,那么这个Consumer Group下的每个实例都生产全量数据。

RocketMQ 数据存储构造

如上图所示,RocketMQ采取了一种数据与索引拆散的存储办法。无效升高文件资源、IO资源,内存资源的损耗。即使是阿里这种海量数据,高并发场景也可能无效升高端到端提早,并具备较强的横向扩大能力。