一、背景
随着移动互联网的迅猛发展,各大互联网公司的体量、业务呈现指数式增长,在业务的反哺与逼迫下,分布式技术架构随之遍地开花,其中以SOA服务技术架构,微服务技术架构等为主的分布式架构如火如荼地发展。在这种大趋势之下,互联网企业也开始面临着数据采集,数据异构,系统整合等诸多问题,而CORBA、DCOM、RMI等RPC中间件技术也应运而生,但由于采用RPC同步处理技术,在性能、健壮性、可扩展性上都存在着诸多缺点,消息队列以异步处理,非阻塞调用的技术模型悄然登场,并迅速成为分布式架构的宠儿。
二、主流消息队列比较
以下表格摘取自apache rocketmq官方文档
阿里云消息队列上有另外一份对比:https://help.aliyun.com/document_detail/52577.html?spm=a2c4g.11186623.6.540.WVgch7
为何选择RocketMQ
- 消息不丢失【重点】
- 强大的技术团队,健壮的社区力量
- 采用Java编写实现,技术体系上更符合团队抉择
- 架构主轻量,组件无状态,可独立部署
- 高可用性,高吞吐量,性能好
- 经历多年阿里巴巴双十一挑战,不管是从业务复杂度,还是高流量并发都扛下来了,故而实践上毋庸置疑
三、简而言之RocketMQ架构
RocketMQ架构分为四个模块
1、生产者
2、消费者
3、namesrv
4、broker
3.1、namesrv
namesrv 是由阿里云RocketMQ中间件开发团队开发的基于服务注册发现功能的无状态组件,支持独立部署。namesrv在整个RocketMQ架构体系中,属于重中之重的组件,乃灵魂级组件,统筹全局,可谓之'一家之主'。上可撩得生产者靓妹,下可驾驭消费者御姐,亦可跟broker徐娘亲近。
那么它又是如何工作的呢?
1、生产者从namesrv中获取可用的broker地址,将消息发送至broker。
2、消费者从namesrv中获取可用的broker地址,从broker中拉去消息。
3、broker定时向naemsrv发送心跳信息,维护可用broker地址。
3.2、broker
broker是由阿里云RocketMQ中间件开发团队开发的基于高性能和低延迟的文件存储的无状态组件,支持独立部署。broker在整个RocketMQ架构体系中,同样是不可或缺的组件,乃核心级组件,可谓之‘持家之女’。负责存储所有的消息相关文件(包括消息文件,日志文件等等)。
3.3、生产者,消费者
生产者,消费者是我们再实际编码过程中直接接触到的,也是RocketMQ直接暴露给编码人员的API接口。生产者是勤勤恳恳的小码农,消费者是奢侈的败家女。
四、集群
4.1、namesrv 集群部署
RocketMQ如何做集群部署来提供系统的吞吐量,以及高可用性?从整体的架构上便可一眼看出,服务注册与发现组件namesrv可以独立部署,且namesrv与namesrv之间并无直接或间接的关联,双方不存在心跳检测,所以namesrv的之间不存在主备切换过程,如果其中一台namesrv宕机后,生产者消费者会直接从另一台namesrv中请求数据。但也正因为namesrv之间不存在心跳检测,主备切换,所以无法支持动态扩容,当机器宕机需要重新部署基于新的ip地址的namesrv需要更新生产者/消费者直连的namesrv地址。
4.2、broker 集群部署
broker支持主从架构
broker支持主从架构模式,但是并非是非常完善的主从架构,据说会在后续版本中优化。
主从架构模式为何会说不是完善的主从架构呢?说到主从 架构模式,大家最熟悉,最耳熟能详的必然是MySQL的主从读写分离模式。主库支持writer,比如insert/update/delete等对数据产生修改的操作,而从库则只支持read操作,这种架构设计是基于目前互联网读多写少的业务模式。
那么RocketMQ又是提供了何种主从读写分离的模式呢?
1、目前它支持master写操作,只有当master读压力高于某个点(master消息拉取出现堆积时),才会将读压力转给salver。
2、无法做到主从切换,master宕机,salver只能提供消息消费,salver不会被选举为master来继续工作。如果master宕机,消息队列整个环境近乎瘫痪。
主从复制
决定rocketmq是否为master还是slaver,是从配置文件中读取设定的,如下:
public enum BrokerRole {
ASYNC_MASTER,
SYNC_MASTER,
SLAVE;
}
ASYNC_MASTER:异步master,也就是新的消息存储时不需要等slave同步好;
SYNC_MASTER:同步master,新消息存现时需要等slave同步好(也就是返回的 Ack Offset >= 当前消息的CommitLog Offset;)
Slave:指该brokder为slaver;
当master启动是,是不会主动向slaver同步数据的。当slaver启动时,会上报当前的commitlog offset偏移值。一般会有两种情况,一种是slaver是全新的机器,commitlog是空的,传递maxPhyOffset=0。一种是master在使用过程中宕机了,经运维人员修复后重启成功,继续工作,master会根据slaver上报的maxPhyOffset的值继续同步。
多master多salver场景
如果用户体量稍微大一些,单master单slaver扛不住,可以采用多master/多slaver部署架构。
broker同步/异步刷盘
前文中我们提到,RocketMQ是基于高性能低延迟的文件储存,为了让用户在使用过程中可以按照自己对消息的丢失容忍程度与性能之间做一个选择,RocketMQ提供了两种方式刷盘方式,即同步刷盘/异步刷盘。顾名思义,同步刷盘指消息投放到broker之后,会在写入文件之后才返回成功,而异步刷盘则指消息投放broker成功后即可返回,同时启动另外的线程来存储消息。
同步刷盘的有点非常明显,可以保证消息可靠性,但是性能上无疑要略逊一筹。
异步刷盘反其道而行之,性能上肯定有了显著提高,但是消息可靠性却无所保证,因为在文件写入过程失败,无法通知生产者重试。
集群与容灾
从RocketMQ的架构设计中可以看到起优雅之处,组件均设计为无状态,所以它强大到可以任何扩展某个一个点。
比如当发现broker压力较大时,可独立扩展broker,只需要将broker地址注册到namesrv中即可。namesrv检测到来自broker的心跳检测后,会将broker信息保存在可用broker列表中。不管是消费者还是生产者,都会按照某个负载均衡算法去选择broker地址。当其中一台broker机器宕机后,namesrv不会顷刻间摘除心跳检测(多次无心跳检测才会摘除),而生产者/消费者亦会有轮询的方式,在数次请求无果后,会从可用列表中将该broker剔除掉,并将请求转发到另外的机器上。
优点:
1、任何组件节点支持集群部署扩展
2、同步刷盘保证数据不丢失,异步主从架构备份(数据可能会缺失)
弊端:
1、不支持master/salver选举,单master部署的情况下,master的宕机几乎是一件毁灭性的打击。
2、主从读写分离的缺陷
参考资料
http://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/
http://rocketmq.apache.org/docs/motivation/
https://help.aliyun.com/document_detail/52577.html?spm=a2c4g.11186623.6.540.WVgch7