本文首先引出消息中间件一般须要解决哪些问题,在解决这些问题当中会遇到什么困难,Apache RocketMQ做为阿里开源的一款高性能、高吞吐量的分布式消息中间件否能够解决,规范中如何定义这些问题。而后本文将介绍RocketMQ的架构设计,以期让读者快速了解RocketMQ。前端
发布订阅是消息中间件的最基本功能,也是相对于传统RPC通讯而言。在此再也不详述。sql
规范中描述的优先级是指在一个消息队列中,每条消息都有不一样的优先级,通常用整数来描述,优先级高的消息先投递,若是消息彻底在一个内存队列中,那么在投递前能够按照优先级排序,令优先级高的先投递。
因为RocketMQ全部消息都是持久化的,因此若是按照优先级来排序,开销会很是大,所以RocketMQ没有特地支持消息优先级,可是能够经过变通的方式实现相似功能,即单独配置一个优先级高的队列,和一个普通优先级的队列, 将不一样优先级发送到不一样队列便可。数据库
对于优先级问题,能够概括为2类:后端
消息有序指的是一类消息消费时,能按照发送的顺序来消费。例如:一个订单产生了3条消息,分别是订单建立,订单付款,订单完成。消费时,要按照这个顺序消费才能有意义。可是同时订单之间是能够并行消费的。
RocketMQ能够严格的保证消息有序。服务器
在Broker中,按照Consumer的要求作过滤,优势是减小了对于Consumer无用消息的网络传输。
缺点是增长了Broker的负担,实现相对复杂。网络
这种过滤方式可由应用彻底自定义实现,可是缺点是不少无用的消息要传输到Consumer端。架构
消息中间件一般采用的几种持久化方式:并发
JMS与CORBA Notification规范没有明确说明如何持久化,可是持久化部分的性能直接决定了整个消息中间件的性能。运维
RocketMQ充分利用Linux文件系统内存cache来提升性能。异步
影响消息可靠性的几种状况:
(1)、(2)、(3)、(4)四种状况都属于硬件资源可当即恢复状况,RocketMQ在这四种状况下能保证消息不丢,或者丢失少许数据(依赖刷盘方式是同步仍是异步)。
(5)、(6)属于单点故障,且没法恢复,一旦发生,在此单点上的消息所有丢失。RocketMQ在这两种状况下,经过异步复制,可保证99%的消息不丢,可是仍然会有极少许的消息可能丢失。经过同步双写技术能够彻底避免单点,同步双写势必会影响性能,适合对消息可靠性要求极高的场合,例如与Money相关的应用。
RocketMQ从3.0版本开始支持同步双写。
在消息不堆积状况下,消息到达Broker后,能马上到达Consumer。
RocketMQ使用长轮询Pull方式,可保证消息很是实时,消息实时性不低于Push。
是指每一个消息必须投递一次。
RocketMQ Consumer先pull消息到本地,消费完成后,才向服务器返回ack,若是没有消费必定不会ack消息,因此RocketMQ能够很好的支持此特性。
只有以上两个条件都知足状况下,才能认为消息是“Exactly Only Once”,而要实现以上两点,在分布式系统环境下,不可避免要产生巨大的开销。因此RocketMQ为了追求高性能,并不保证此特性,要求在业务上进行去重,也就是说消费消息要作到幂等性。RocketMQ虽然不能严格保证不重复,可是正常状况下不多会出现重复发送、消费状况,只有网络异常,Consumer启停等异常状况下会出现消息重复。
Broker的Buffer一般指的是Broker中一个队列的内存Buffer大小,这类Buffer一般大小有限,若是Buffer满了之后怎么办?
下面是CORBA Notification规范中处理方式:
RocketMQ没有内存Buffer概念,RocketMQ的队列都是持久化磁盘,数据按期清除。
对于此问题的解决思路,RocketMQ同其余MQ有很是显著的区别,RocketMQ的内存Buffer抽象成一个无限长度的队列,无论有多少数据进来都能装得下,这个无限是有前提的,Broker会按期删除过时的数据,例如Broker只保存3天的消息,那么这个Buffer虽然长度无限,可是3天前的数据会被从队尾删除。
此问题的本质缘由是网络调用存在不肯定性,即既不成功也不失败的第三种状态,因此才产生了消息重复性问题。
回溯消费是指Consumer已经消费成功的消息,因为业务上需求须要从新消费,要支持此功能,Broker在向Consumer投递成功消息后,消息仍然须要保留。而且从新消费通常是按照时间维度,例如因为Consumer系统故障,恢复后须要从新消费1小时前的数据,那么Broker要提供一种机制,能够按照时间维度来回退消费进度。
RocketMQ支持按照时间回溯消费,时间维度精确到毫秒,能够向前回溯,也能够向后回溯。
消息中间件的主要功能是异步解耦,还有个重要功能是挡住前端的数据洪峰,保证后端系统的稳定性,这就要求消息中间件具备必定的消息堆积能力,消息堆积分如下两种状况:
评估消息堆积能力主要有如下四点:
已知的几个分布式事务规范,6080新影视如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消费消息失败一般能够认为有如下几种状况:
RocketMQ是否解决了上述消息中间件面临的问题,接下来让咱们一探究竟。
上图是一个典型的消息中间件收发消息的模型,RocketMQ也是这样的设计,简单说来,RocketMQ具备如下特色:
如上图所示, RocketMQ的部署结构有如下特色:
如上图所示,RocketMQ的逻辑部署结构有Producer和Consumer两个特色。
Producer Group
用来表示一个发送消息应用,一个Producer Group下包含多个Producer实例,能够是多台机器,也能够是一台机器的多个进程,或者一个进程的多个Producer对象。一个Producer Group能够发送多个Topic消息,Producer Group做用以下:
Consumer Group
用来表示一个消费消息应用,一个Consumer Group下包含多个Consumer实例,能够是多台机器,也能够是多个进程,或者是一个进程的多个Consumer对象。一个Consumer Group下的多个Consumer以均摊方式消费消息,若是设置为广播方式,那么这个Consumer Group下的每一个实例都消费全量数据。
如上图所示,RocketMQ采起了一种数据与索引分离的存储方法。有效下降文件资源、IO资源,内存资源的损耗。即使是阿里这种海量数据,高并发场景也可以有效下降端到端延迟,并具有较强的横向扩展能力。