1. 消息中间件简介
目前主要提供了无序事务性高性能消息队列Notify与有序高性能消息队列RocketMQ(MetaQ)两大类产品,目前RocketMQ已经开源(https://github.com/alibaba/RocketMQ),产品被包括核心交易在内的几乎所有的应用所使用,每秒钟消息量80W,这对于消息投递与消息存储与运维来说,都是个巨大的挑战,而如何能够更合理的使用更低的机器成本与运维成本来满足用户不断增长的消息发送需求,是整个团队最大的价值所在。
目前团队主要的工作内容是:
1、依托实际的业务场景和新的软硬件,降低消息系统的成本
2、维护开源产品,为社区贡献一些自己的力量
3、依托新的业务场景,创造符合新场景的消息模型与消息系统
2. Notify无序消息投递
消息系统的核心作用就是三点:解耦,异步和并行。
Notify的核心特性是: 提供事务支持、不保证消息顺序、消息可能会重复、推模型。
2.1 引入原因
通过业务分析我们能够得知,用户的实际的核心流程其实只有一个,就是用户注册。而后续的准备支付宝,通知sns等操作虽然必须要完成,但却是不需要让用户等待的。这种模式有个专业的名词,就叫最终一致。为了达到最终一致,我们引入了MQ系统。
2.2 设计理念
Notify在设计思路上与传统的MQ有一定的不同:
1. 为了消息堆积而设计系统
2. 无单点,可自由扩展的设计
在Notify的整体设计中,我们最优先考虑的就是消息堆积问题,在目前的设计中我们使用了持久化磁盘的方式,在每次用户发消息到Notify的时候都将消息先落盘,然后再异步的进行消息投递,而没有采用激进的使用内存的方案来加快投递速度。
2.3 五个核心部分
l 发送消息的集群这主要是业务方的机器,这些APP的机器上是没有任何状态信息的,可以随着用户请求量的增加而随时增加或减少业务发送方的机器数量,从而扩大或缩小集群能力。
l 配置服务器集群(Config server)这个集群的主要目的是动态的感知应用集群,消息集群机器上线与下线的过程,并及时广播给其他集群。如当业务接受消息的机器下线时,config server会感知到机器下线,从而将该机器从目标用户组内踢出,并通知给notify server,notify server 在获取通知后,就可以将已经下线的机器从自己的投递目标列表中删除,这样就可以实现机器的自动上下线扩容了。
l 消息服务器(Notify Server)消息服务器,也就是真正承载消息发送与消息接收的服务器,也是一个集群,应用发送消息时可以随机选择一台机器进行消息发送,任意一台server 挂掉,系统都可以正常运行。当需要增加处理能力时,只需要简单地增加notify Server就可以了
l 存储(Storage)Notify的存储集群有多种不同的实现方式,以满足不同应用的实际存储需求。针对消息安全性要求高的应用,我们会选择使用多份落盘的方式存储消息数据,而对于要求吞吐量而不要求消息安全的场景,我们则可以使用内存存储模型的存储。自然的,所有存储也被设计成了随机无状态写入存储模型以保障可以自由扩展。
l 消息接收集群业务方用于处理消息的服务器组,上下线机器时候也能够动态的由config server 感知机器上下线的时机,从而可以实现机器自动扩展。
3. METAQ开源消息中间件
3.1 特性
METAQ是一款完全的队列模型消息中间件,服务器使用Java语言编写,可在多种软硬件平台上部署。客户端支持Java、C++编程语言,已于2012年3月对外开源,开源地址是:http://metaq.taobao.org/。MetaQ大约经历了下面3个阶段
在2011年1月份发布了MetaQ 1.0版本,从Apache Kafka衍生而来,在内部主要用于日志传输。
在2012年9月份发布了MetaQ 2.0版本,解决了分区数受限问题,在数据库binlog同步方面得到了广泛的应用。
在2013年7月份发布了MetaQ 3.0版本,MetaQ开始广泛应用于订单处理,cache同步、流计算、IM实时消息、binlog同步等领域。
MetaQ适合的场景?
日志传输,高吞吐量的日志传输,这本来也是kafka的强项。
消息广播功能,如广播缓存配置失效。
数据的顺序同步功能,如MySQL binlog复制。
分布式环境下(broker、producer、consumer都为集群)的消息路由,对顺序和可靠性有极高要求的场景。
作为一般MQ来使用的其他功能
MetaQ借鉴了Kafka的思想,并结合互联网应用场景对性能的要求,对数据的存储结构进行了全新设计。在功能层面,增加了更适合大型互联网特色的功能点。
采用pull机制,而不是一般MQ的push模型,它大量利用了zookeeper做服务发现和offset存储。
MetaQ对外提供的是一个队列服务,内部实现也是完全的队列模型,这里的队列是持久化的磁盘队列,具有非常高的可靠性,并且充分利用了操作系统cache来提高性能。
- 是一个队列模型的消息中间件,具有高性能、高可靠、高实时、分布式特点。
- Producer、Consumer、队列都可以分布式。
- Producer向一些队列轮流发送消息,队列集合称为Topic,Consumer如果做广播消费,则一个consumer实例消费这个Topic对应的所有队列,如果做集群消费,则多个Consumer实例平均消费这个topic对应的队列集合。
- 能够保证严格的消息顺序
- 提供丰富的消息拉取模式
- 高效的订阅者水平扩展能力
- 实时的消息订阅机制
- 亿级消息堆积能力
3.2 MetaQ与Notify区别
- Notify侧重于交易消息,分布式事务消息方面。
- MetaQ侧重于顺序消息场景,例如binlog同步。以及主动拉消息场景,例如流计算等。
- RocketQ(MetaQ) 主要面向消息有序的场景,能够提供更大的消息堆积能力
- Notify,主要面向需要更加安全可靠地交易类场景,无序,推模式。
3.3 Meta相对于kafka特有的一些功能
- 文本协议设计,非常透明,支持类似memcached stats的协议来监控broker
- 纯Java实现,从通讯到存储,从client到server都是重新实现。
- 提供事务支持,包括本地事务和XA分布式事务
- 支持HA复制,包括异步复制和同步复制,保证消息的可靠性
- 支持异步发送消息
- 消费消息失败,支持本地恢复
- 多种offset存储支持,数据库、磁盘、zookeeper,可自定义实现
- 支持group commit,提升数据可靠性和吞吐量。(目前kafka已实现)
- 支持消息广播模式
- 一系列配套项目:Python/Ruby/C/C++客户端、Twitter Storm的Spout、Tail4j等。
3.4 MetaQ的内部是如何实现的?
从实现角度看,MetaQ充分利用zookeeper这个优秀的服务中心,作为服务注册和查找中心、客户端负载均衡和数据偏移量的分布式存储使用。Zookeeper在MetaQ整个集群中扮演非常关键的角色。
MetaQ的存储实现与kafka是一致的,充分利用传统磁盘顺序读写非常高效的特点,并且利用group commit、sendfile系统调用等技术来充分提高IO效率。
MetaQ的事务实现跟ActiveMQ是类似的,采用redo日志的方式,并遵循JTA协议规范来实现分布式事务。
MetaQ的网络协议跟memcached文本协议类似,因为我本人非常熟悉memcached(开源的xmemcached客户端是我开发的),但是MetaQ的协议引入了opaque的映射字段,提高请求的并行度。正因为采用文本协议,为MetaQ编写其他语言客户端是相对容易,并且管理MetaQ服务器也变的很容易,比如MetaQ提供了stats协议,通过telent就可以获取服务器的运行状况。
关于更多的实现细节可以看Wiki上的文档:
https://github.com/killme2008/Metamorphosis/wiki/design
https://github.com/killme2008/Metamorphosis/wiki/协议
4. 文章
a) 消息中间件-Notify的概念和原理
b) 淘宝消息中间件技术演变
c) 阿里中间件团队博客:http://jm.taobao.org/
d) 阿里巴巴消息中间件团队消息和分布式数据层负责人王晶昱:消息系统架构与变迁:http://www.infoq.com/cn/news/2014/03/interview-alibaba-wangjingyu/
e) 分布式消息中间件 MetaQ 作者庄晓丹专访:http://www.iteye.com/magazines/107