目录

RabbitMQ

Kafka

ActiveMQ

RabbitMQ与Kafka比较


解耦神器:消息中间件(MQ)

目前市面上消息中间件有很多,比如商业MQ:MSMQ、IBM MQ、JBoss MQ,开源免费的如:ActiveMQ、RabbitMQ、RocketMQ、Kafka等等,各种MQ特点不同使用场景也不一样。对于商业MQ而言其稳定安全效率高,常用于政府或金融机构。而开源MQ则常见于互联网公司。我用过其中的四个MQ:IBMMQ、RabbitMQ、Kafka和ActiveMQ。

IBMMQ一个老牌MQ性能强劲,稳定又安全,但是要钱,而且价格不菲。

RabbitMQ

RabbitMQ由于具有应答和确认模式常见于对数据准确性要求较高的场景,常用于企业级开发。它是用Erlang编写的一种实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。它的灵感来源于交换机。包括生产者、消费者、队列和交换机。生产者及消息发送者。消费者及消息接收者。队列就是存储待消费数据的地方,队列本质上是一个无限数据缓冲区。交换机及转发消息的载体,它不存储数据只负责数据的转发,在启动之初交换机会为每一个连接的队列设置一个路由键及routing_key,当有消息需要发送时会通过这个路由键来决定发送到某个或某些队列。交换机有四种类型:Direct、Topic、Headers和Fanout。

Direct:路由键全匹配原则,发送的队列和接收的队列路由键必须完全一样才可以转发消息。

Topic:根据通配符转发消息。

在这种交换机模式下:

  • 路由键必须是一串字符,用句号(.) 隔开,比如说 agreements.us,或者 agreements.eu.stockholm 等。
  • 路由模式必须包含一个 星号(*),主要用于匹配路由键指定位置的一个单词,比如说,一个路由模式是这样子:agreements..b.*,那么就只能匹配路由键是这样子的:第一个单词是 agreements,第四个单词是 b。 井号(#)就表示相当于一个或者多个单词,例如一个匹配模式是agreements.eu.berlin.#,那么,以agreements.eu.berlin开头的路由键都是可以的。
  • *表示一个词.
  • #表示零个或多个词

Headers:根据自定义匹配规则来转发消息。在队列与交换器绑定时,会设定一组键值对规则,消息中也包括一组键值对( headers 属性),当这些键值对有一对,或全部匹配时, 消息被投送到对应队列。

Fanout:广播模式,不管路由键只要是绑定该交换机的队列都会转发消息。

Kafka

Kafka是由scala+java编写的一款用于大数据量处理的高吞吐量的分布式的支持分区的基于ZK协调的发布订阅系统,他可以实时处理大数据量以满足应用场景。Kafka采用Zerocopy原则,及采用由内核直接到内核,传统的数据传输需要先复制到内核空间(read是系统调用,放到了DMA,所以用内核空间),然后复制到用户空间;从用户空间重新复制到内核空间(你用的socket是系统调用,所以它也有自己的内核空间),最后发送给网卡,而kafka直接从内核复制,继而通过网关发送省却了很多步骤,而且kafka是通过顺序写数据,及新增数据会直接加到数据结尾省却了内存数据重排序。kafka没有确认机制,当消息投递出去后它不会等待投递成功确认消息,因此kafka效率是极高的,是目前运行效率最高的MQ。kafka支持数据分区,每一个分区都有一个全量副本以保证高可用,越多的分区意味着越高的吞吐量只要机器配置足够理论上可以无限分区,但也意味着可用性降低。kafka对消息保存时根据Topic进行归类,发送消息者成为Producer,消息接受者成为Consumer,此外kafka集群有多个kafka实例组成,每个实例成为broker。无论是kafka集群,还是producer和consumer都依赖于zookeeper来保证系统可用性集群保存一些meta信息。kafka必须搭配ZK使用。

Topics/logs

一个Topic可以认为是一类消息,每个topic将被分成多个partition(区),每个partition在存储层面是append log文件。任何发布到此partition的消息都会被直接追加到log文件的尾部,每条消息在文件中的位置称为offset(偏移量),offset为一个long型数字,它是唯一标记一条消息。它唯一的标记一条消息。kafka并没有提供其他额外的索引机制来存储offset,因为在kafka中几乎不允许对消息进行“随机读写”。

Distribution

    一个Topic的多个partitions,被分布在kafka集群中的多个server上;每个server(kafka实例)负责partitions中消息的读写操作;此外kafka还可以配置partitions需要备份的个数(replicas),每个partition将会被备份到多台机器上,以提高可用性。基于replicated方案,那么就意味着需要对多个备份进行调度;每个partition都有一个server为"leader";leader负责所有的读写操作,如果leader失效,那么将会有其他follower来接管(成为新的leader);follower只是单调的和leader跟进,同步消息即可。由此可见作为leader的server承载了全部的请求压力,因此从集群的整体考虑,有多少个partitions就意味着有多少个"leader",kafka会将"leader"均衡的分散在每个实例上,来确保整体的性能稳定。

ActiveMQ

 ActiveMQ是Apache软件基金会所研发的开放源代码消息中间件;由于ActiveMQ是一个纯Java程序,因此只需要操作系统支持Java虚拟机,ActiveMQ便可执行。

 多种语言和协议编写客户端。语言: Java,C,C++,C#,Ruby,Perl,Python,PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP

 完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)

 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去通过了常见J2EE服务器(如 Geronimo,JBoss 4,GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上

 支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA

 支持通过JDBC和journal提供高速的消息持久化

 从设计上保证了高性能的集群,客户端-服务器,点对点

 支持Ajax

 支持与Axis的整合

 可以很容易的调用内嵌JMS provider,进行测试

术语介绍

术语

说明

Destination

目的地,JMS Provider(消息中间件)负责维护,用于对Message进行管理的对象。MessageProducer需要指定Destination才能发送消息,MessageReceiver需要指定Destination才能接收消息。

Producer

消息生成者,负责发送Message到目的地。

Consumer | Receiver

消息消费者,负责从目的地中消费【处理|监听|订阅】Message

Message

消息,消息封装一次通信的内容。

云原生中间件 开源_kafka

RabbitMQ与Kafka比较

rabbitmq有ack确认机制,确认机制是没有时间限制的直至,没有确认时会一直挂起与该消费者连接中断,会认为消息投递失败继而转发到其他消费者消费,也就是说rabbitmq其实是可以回滚的。kafka是没有确认机制的,它在消息投递之后便立即投递下一个消息至于消息有没有正确消费它不会在意。rabbitmq的消息在一个队列中是有顺序的并且是严格按照先进先出原则消费,kafka在同一个分片中是有顺序的但放入队列中的顺序是放在不同的分区的因此无法保证总的数据顺序。rabbitmq在不使用ack确认机制时吞吐量可达6W但使用ack机制后吞吐量会下降至1W左右,而kafka吞吐量巨大它对于磁盘数据都是批量处理并使用zerocopy模式吞吐量可达百万级。对于可靠性来讲,rabbitmq使用MirrorQueue机制可以进行多台机器热备,而kafka只可以通过broker进行主备。rabbitmq和kafka都支持持久化数据,甚至有些公司直接使用kafka队列作为数据库。对于他们的使用场景,rabbitmq应当用来处理实时且可靠性高的消息,且消息量要尽可能的小,消费者与生产者要尽量对等,而且最好可以部署多态热备机器以充分利用其高可用特性。当使用kafka时则必须要搭建监控系统,不仅要监控kafka还要监控ZK,要确保对消息的可靠性、实时性和消息的顺序性都不是很重要,对应的数据量要极大对吞吐量有一定要求。

mq常用于程序间的解耦,像kafka常用于日志传输、大数据流、文件系统、数据库等大数据场景,rabbitmq常用于电商系统的订单投递、商品投递、支付队列或用于金融行业的行情投递等对消息可靠性要求较高的场景,甚至有些公司使用mq作为微服务通讯媒介,总之使用范围很广,是使用频率很高的工具。