RabbitMQ
RabbitMQ是实现AMQP协议(0.9.1) 的消息中间件的一种,由RabbitMQ Technologies Ltd开发并且提供商业支持的,最初起源于金融系统,服务器端用Erlang语言编写,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
RabbitMQ基本概念
- Broker: 简单来说就是消息队列服务器实体
- Exchange: 消息交换机,它指定消息按什么规则,路由到哪个队列
- Queue: 消息队列载体,每个消息都会被投入到一个或多个队列
- Binding: 绑定,它的作用就是把exchange和queue按照路由规则绑定起来
- Routing Key: 路由关键字,exchange根据这个关键字进行消息投递
- VHost: vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。
- Producer: 消息生产者,就是投递消息的程序
- Consumer: 消息消费者,就是接受消息的程序
- Channel: 消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务
由Exchange、Queue、RoutingKey三个才能决定一个从Exchange到Queue的唯一的线路。
RabbitMQ处理流程
1.Producer会先建立Channel,建立到Broker上Virtual Host的连接,接下来就可以向这个Virtual Host中的Exchange发送消息。
2.Producer把消息发布到Exchange上,消息最终到达队列并被消费者接收,而Binding决定交换器的消息应该发送到那个队列。Exchange能够处理消息的前提是,它至少已经和某个Queue或者另外的Exchange形成了绑定关系,并设置好了到这些Queue和Excahnge的路由规则。在Exchange收到消息后,会根据设置的路由规则,将消息发送到符合要求的Queue或者Exchange中(路由规则与Message中的Routing Key属性配合使用)。
3.当Queue收到消息后,会进行如下处理:
- 如果当前没有Consumer的Channel连接到这个Queue,那么Queue将会把这条消息进行存储,直到有Channel被创建。
- 如果已经有Channel连接到这个Queue,那么消息将会按顺序发送给这个Channel。
4.当Consumer收到消息后,就可以进行消息的处理:
- Consumer在完成某一条消息的处理后,将需要手动的发送一条ACK消息到对应的Queue,也可以设置为自动发送或者无需发送。
- Queue在接收到这条ACK信息后,才认为这条消息处理成功,并将这条消息从Queue中移除。
- 如果在对应的Channel断开后,Queue都没有这条消息的ACK信息,这条消息将会重新被发送给另外的Channel。也可以直接发送NACK信息,这样这条消息将会立即归队,并发送给另外的Channel。
RabbitMQ的工作模式
simple模式(即最简单的收发模式)
1.消息产生消息,将消息放入队列
2.消息的消费者(consumer) 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除(隐患 消息可能没有被消费者正确处理,已经从队列中消失了,造成消息的丢失,这里可以设置成手动的ack,但如果设置成手动ack,处理完后要及时发送ack消息给队列,否则会造成内存溢出)。
work工作模式(资源的竞争)
1.消息产生者将消息放入队列。
2.消费者可以有多个,消费者1,消费者2同时监听同一个队列,消息被消费。C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息(隐患:高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize) 保证一条消息只能被一个消费者使用)。
publish/subscribe发布订阅(共享资源)
1、每个消费者监听自己的队列;
2、生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息。
routing路由模式
1.消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息;
2.根据业务功能定义路由字符串
3.从系统的代码逻辑中获取对应的功能字符串,将消息任务扔到对应的队列中。
4.业务场景:error 通知;EXCEPTION;错误通知的功能;传统意义的错误通知;客户通知;利用key路由,可以将程序中的错误封装成消息传入到消息队列中,开发者可以自定义消费者,实时接收错误;
topic 主题模式(路由模式的一种)
1.星号(*)井号(#)代表通配符
2.星号(*)代表多个单词,井号(#)代表一个单词
3.路由功能添加模糊匹配
4.消息产生者产生消息,把消息交给交换机
5.交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费
RabbitMQ优点
- 由于erlang语言的特性,mq 性能较好,高并发;
- 健壮、稳定、易用、跨平台、支持多种语言、文档齐全;
- 有消息确认机制和持久化机制,可靠性高;
- 高度可定制的路由;
- 管理界面较丰富,在互联网公司也有较大规模的应用;
- 社区活跃度高;
RabbitMQ缺点
- 尽管结合erlang语言本身的并发优势,性能较好,但是不利于做二次开发和维护;
- 实现了代理架构,意味着消息在发送到客户端之前可以在中央节点上排队。此特性使得RabbitMQ易于使用和部署,但是使得其运行速度较慢,因为中央节点增加了延迟,消息封装后也比较大;
- 需要学习比较复杂的接口和协议,学习和维护成本较高;
Kafka
Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因素。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。 对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka的目的是通过Hadoop的并行加载机制来统一线上和离线的消息处理,也是为了通过集群来提供实时的消息。
Kafka基本概念
-
Broker
消息中间件处理节点,一个Kafka节点就是一个Broker,一个或者多个Broker可以组成一个Kafka集群
-
Topic
每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)
-
Partition
用于存放消息的队列,存放的消息都是有序的,同一主题可以分多个Partition,如分多个Partiton时,同样会以如partition1存放1、3、5消息,partition2存放2、4、6消息
-
Producer
消息生产者,向Broker发送消息的客户端
-
Consumer
消息消费者,从Broker读取消息的客户端,Consumer是通过offset进行标识消息被消费的位置
-
Consumer Group
每个Consumer属于一个特定的Consumer Group,一条消息可以发送到多个不同的Consumer Group,但是同一个Consumer Group中只能有一个Consumer能够消费该消息
Kafka数据处理步骤
- Producer产生消息,发送到Broker中
- Leader状态的Broker接收消息,写入到相应topic中
- Leader状态的Broker接收完毕以后,传给Follow状态的Broker作为副本备份
- Consumer消费Broker中的消息
Kafka优点
- 客户端语言丰富,支持java、.net、php、ruby、python、go等多种语言;
- 性能卓越,单机写入TPS约在百万条/秒,消息大小10个字节;
- 提供完全分布式架构, 并有replica机制, 拥有较高的可用性和可靠性, 理论上支持消息无限堆积;
- 支持批量操作;
- 消费者采用Pull方式获取消息, 消息有序, 通过控制能够保证所有消息被消费且仅被消费一次;
- 有优秀的第三方Kafka Web管理界面Kafka-Manager;
- 在日志领域比较成熟,被多家公司和多个开源项目使用;
Kafka缺点
- Kafka单机超过64个队列/分区,Load会发生明显的飙高现象,队列越多,load越高,发送消息响应时间变长
- 使用短轮询方式,实时性取决于轮询间隔时间;
- 消费失败不支持重试;
- 支持消息顺序,但是一台代理宕机后,就会产生消息乱序;
- 社区更新较慢;
RocketMQ
RocketMQ 是阿里巴巴在2012年开源的分布式消息中间件,目前已经捐赠给 Apache 软件基金会,并于2017年9月25日成为 Apache 的顶级项目。作为经历过多次阿里巴巴双十一这种“超级工程”的洗礼并有稳定出色表现的国产中间件,以其高性能、低延时和高可靠等特性近年来已经也被越来越多的国内企业使用。
RocketMQ基本概念
生产者组(Producer)
负责产生消息,生产者向消息服务器发送由业务应用程序系统生成的消息。 RocketMQ 提供了三种方式发送消息:同步、异步和单向。
名称服务器(NameServer)
主要负责对于源数据的管理,包括了对于Topic和路由信息的管理。
NameServer 被设计成几乎无状态的,可以横向扩展,节点之间相互之间无通信,通过部署多台机器来标记自己是一个伪集群。每个 Broker 在启动的时候会到 NameServer 注册,Producer 在发送消息前会根据 Topic 到 NameServer 获取到 Broker 的路由信息,Consumer 也会定时获取 Topic 的路由信息。所以从功能上看应该是和 ZooKeeper 差不多,RocketMQ 的早期版本确实是使用的 ZooKeeper ,后来改为了自己实现的 NameServer 。
消息服务器(Broker)
是消息存储中心,主要作用是接收来自 Producer 的消息并存储, Consumer 从这里取得消息。它还存储与消息相关的元数据,包括用户组、消费进度偏移量、队列信息等。从部署结构图中可以看出 Broker 有 Master 和 Slave 两种类型,Master 既可以写又可以读,Slave不可以写只可以读。从物理结构上看 Broker 的集群部署方式有四种:单 Master 、多 Master 、多 Master 多 Slave(同步刷盘)、多 Master多 Slave(异步刷盘)。
消费者组(Consumer)
负责消费消息,消费者从消息服务器拉取信息并将其输入用户应用程序,支持PUSH和PULL两种消费模式,支持集群消费和广播消息,提供实时的消息订阅机制。
- Pull:拉取型消费者(Pull Consumer)主动从消息服务器拉取信息,只要批量拉取到消息,用户应用就会启动消费过程,所以 Pull 称为主动消费型。
- Push:推送型消费者(Push Consumer)封装了消息的拉取、消费进度和其他的内部维护工作,将消息到达时执行的回调接口留给用户应用程序来实现。所以 Push 称为被动消费类型,但从实现上看还是从消息服务器中拉取消息,不同于 Pull 的是 Push 首先要注册消费监听器,当监听器处触发后才开始消费消息。
RocketMQ特性
1.灵活可扩展性 : 天然支持集群,其核心四组件(Name Server、Broker、Producer、Consumer)每一个都可以在没有单点故障的情况下进行水平扩展。
2.海量消息堆积: 采用零拷贝原理实现超大的消息的堆积能力,据说单机已可以支持亿级消息堆积,而且在堆积了这么多消息后依然保持写入低延迟。
3.顺序消息: 可以保证消息消费者按照消息发送的顺序对消息进行消费。顺序消息分为全局有序和局部有序,一般推荐使用局部有序,即生产者通过将某一类消息按顺序发送至同一个队列来实现。
4.消息过滤: 分为在服务器端过滤和在消费端过滤。服务器端过滤时可以按照消息消费者的要求做过滤,优点是减少不必要消息传输,缺点是增加了消息服务器的负担,实现相对复杂。消费端过滤则完全由具体应用自定义实现,这种方式更加灵活,缺点是很多无用的消息会传输给消息消费者。
5.事务消息: 除了支持普通消息,顺序消息之外还支持事务消息,这个特性对于分布式事务来说提供了又一种解决思路。
6.消息回溯: 是指消费者已经消费成功的消息,由于业务上需求需要重新消费,RocketMQ 支持按照时间回溯消费,时间维度精确到毫秒,可以向前回溯,也可以向后回溯。
RocketMQ优点
- 单机支持 1 万以上持久化队列
- RocketMQ 的所有消息都是持久化的,先写入系统 PAGECACHE,然后刷盘,可以保证内存与磁盘都有一份数据,访问时,直接从内存读取。
- 模型简单,接口易用(JMS 的接口很多场合并不太实用);
- 性能非常好,可以大量堆积消息在broker中;
- 支持多种消费,包括集群消费、广播消费等。
- 各个环节分布式扩展设计,主从HA;
- 开发度较活跃,版本更新很快。
RocketMQ缺点
- 支持的客户端语言不多,目前是java及c++,其中c++不成熟;
- RocketMQ社区关注度及成熟度不高;
- 没有web管理界面,提供了一个CLI(命令行界面)管理工具带来查询、管理和诊断各种问题;
- 没有在 mq 核心中去实现JMS等接口;
ActiveMQ
ActiveMQ是由Apache出品,旨在为应用程序提供高效、可扩展、稳定、安全的企业级消息通信,它是一个完全支持JMS1.1和J2EE 1.4规范的JMS Provider实现,比如 JMX 管理、主从管理、消息组通信、消息优先级、延迟接收消息、虚拟接收者、消息持久化、消息队列监控等等。它非常快速,支持多种语言的客户端和协议,而且可以非常容易的嵌入到企业的应用环境中,并有许多高级功能。
和上面的mq类似,主要的基本组件有Broker、Producer、Consumer、Topic、Queue、Message
ActiveMQ优点
- 跨平台(JAVA编写与平台无关有,ActiveMQ几乎可以运行在任何的JVM上)
- 可以用JDBC:可以将数据持久化到数据库。虽然使用JDBC会降低ActiveMQ的性能,但是数据库一直都是开发人员最熟悉的存储介质。将消息存到数据库,看得见摸得着。而且公司有专门的DBA去对数据库进行调优,主从分离;
- 支持JMS :支持JMS的统一接口;
- 支持自动重连;
- 有安全机制:支持基于shiro,jaas等多种安全配置机制,可以对Queue/Topic进行认证和授权。
- 监控完善:拥有完善的监控,包括Web Console,JMX,Shell命令行,Jolokia的REST API;
- 界面友善:提供的Web Console可以满足大部分情况,还有很多第三方的组件可以使用,如hawtio;
ActiveMQ缺点
- 社区活跃度不及RabbitMQ高;
- 根据其他用户反馈,会出莫名其妙的问题,会丢失消息;
- 对5.x的维护较少;
- 不适合用于上千个队列的应用场景;
RabbitMQ、Kafka、RocketMQ、ActiveMQ对比
特性 | RabbitMQ | Kafka | RocketMQ | ActiveMQ |
---|---|---|---|---|
开发语言 | Erlang | Scala&Java | Java | Java |
客户端支持 | 官方支持Erlang、Java、Ruby等,社区产出多语言API,几乎支持所有常用语言 | 官方支持Java,社区有多语言版本,如PHP、Python、Go、C/C++、Ruby、NodeJs等 | Java、C++ | Java、C/C++、Python、PHP、Perl、.net等 |
协议支持 | AMQP、XMPP、SMTP、SMTOP | 自定义协议,社区提供了HTTP协议支持 | 自定义协议,社区提供JMS | OpenWire、SMTOP、REST、XMPP、AMQP |
可用性 | 高,基于主从架构实现高可用 | 很高,分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 | 很高,分布式架构 | 高,基于主从架构实现高可用 |
集群 | 支持 | 支持 | 支持 | 支持 |
负载均衡 | 支持 | 支持 | 支持 | 支持 |
单机吞吐量 | 万级 | 十万级 | 十万级 | 万级 |
topic数量对吞吐量的影响 | - | topic从几十到几百个时候,吞吐量会大幅度下降,因为Kafka的每个Topic、每个分区都会对应一个物理文件,若需要支撑大规模的topic,则需要增加更多的机器资源 | topic达到几百/几千的级别后,吞吐量会有较小幅度的下降,在同等机器下,可以支撑大量的 topic | - |
消息批量操作 | 不支持 | 支持 | 支持 | 支持 |
消息推拉模式 | pull/push均支持 | pull | pull/push均支持 | pull/push均支持 |
消息可靠性 | 支持最少投递一次 | 支持最少投递一次 | 支持最少投递一次 | 有较低的概率丢失数据 |
消息延迟 | 微秒级 (最快) | 毫秒级 | 毫秒级 | 毫秒级 |
持久化能力 | 内存、文件,支持数据堆积,但影响生产速率 | 磁盘文件,只要容量够,可以做到无限堆积 | 磁盘文件 | 内存、文件、数据库 |
事务消息 | 不支持 | 不支持 | 支持 | 支持 |
死信 | 支持 | 不支持 | 支持 | 支持 |
消息回放 | 不支持 | 支持offset维度回放 | 支持offset维度回放 | 不支持 |
延迟队列 | 支持 | 不支持 | 支持 | 支持 |