ActiveMQ、RabbitMQ、Kafka、RocketMQ的区别

ActiveMQ

老牌消息队列,是Java写的mq,但支持C,C++,PHP,python等各客户端,配置和使用基本上是Java xml这一套,同时对spring支持比较友好。在java程序中,也可以作为jar包放在java项目里面。
activemq支持主从复制,集群,但集群功能很弱,只支持failover,即连一个broker失败了,可以转到其他broker来,但这样有一个缺陷,当有三个broker的时,其中有一个是没有consumer的,但另外两个挂了,信息还是会存入到这个broker,然后会将消息不断堆积。

acticemq只支持两个模式 queue 和 topic

queue

也就是多对一的通信,producer 将消息传入queue里面,consumer去queue里面取消息,这里它还有messageGroup的概念,也就是消费者组,当一个消费者消费不够快时,可以将多个消费者放入一个messageGroup,queue会轮流发给组里的消费者,每个消息只会消费一次。

topic

广播,producer发布带有topic标示的消息,消费者订阅感兴趣的topic,所有订阅了topic的消费者都会收到消息。订阅分为持久和不持久。持久订阅,当消费者断开一段时间再连上了,中间的消息会发送给消费者。不持久的话,消费者断开那段时间的消息是不会发给消费者的。

RabbitMQ

rabbitMQ是用erlang写的,功能比activeMQ多,有实例,用户权限,监控系统,当然也更复杂。
从机制上讲,rabbitMQ也有queue,topic的概念,但其多了一个概念叫交换机,一条消息的传播过程为producer->exchang->queue->consumer , 生产者发送的信息都会带有key表示发送给哪一个交换机,再由交换机发送给队列。

交换机有四种 direct fanout topic header

direct

直连交换机,与该交换机绑定的队列都会绑定一个routingKey,交换机会根据生产者发送的消息里的routingKey转发给相应的队列。
比如有一个直连交换机 direct1 ,4个队列 queue1,queue2,queue3,queue4,其中queue1 与 queue2绑定keya,queue3和queue4绑定keyb,。交换机在收到带有keya的消息时,会发送给queue1与queue2。收到keyb的消息时,会发送给queue3和queue4。

fanout

扇形交换机,也就是广播,该交换机接收到的消息会发送给与它绑定的所有队列。
总体来说,fanout就是direct实现的,当绑定到交换机的队列的key一样时,direct也就成了fanout。

topic

主题交换机,与direct比,多了一个通配符匹配规则,队列和交换机绑定key需要采用*.#…的格式。单词间用.分隔开
*代表一个单词,#代表多个单词
比如有四条队列绑定的key分别为 bat.# , .man.super.man, #.supper.,#.man
那么当发送一条key为bat.man.super.man的消息时,这四条队列都会收到消息。

header

首部交换机,这个交换机很少使用到,其忽略了routingKey,而是根据发送的消息内容中的headers属性进行匹配。

Kafka

kafka是一个分布式流处理平台,可以发布,订阅流式记录,存储流式记录,在记录产生时进行处理。
它可以用于两大类别的应用:
构造实时流数据管道,它可以在系统或应用之间可靠地获取数据。 (相当于message queue)
构建实时流式应用程序,对这些流数据进行转换或者影响。 (就是流处理,通过kafka stream topic和topic之间内部进行变化)

先理解kafka的一些名词角色。

  • producer 生产者,向kafka的broker发送消息的客户端
  • consumer 消费者,从broker拉取消息
  • consumerGroup 消费者组,所有消费者都属于一个消费者组,消费组是逻辑上的订阅者
  • broker 一个kafka服务就是一个broker
  • topic 主题,kafka的消息以topic分类,消费者组会指定要消费的topic,一个消费者可以消费多个topic,一个topic可以被多个消费者消费。
  • partition 分区,一个topic的消息可以分为多个分区存储,一个分区的消息只能由同一个消费组里的一个消费者消费,但同一个组的消费者可以消费多个分区。
  • replication 副本,kafka集群中,每一个分区有多个副本,每一个broker中每一个分区只有一个副本。
  • leader 主副本,消息的生产和消费都是与主副本来交互的,产生与消费的消息会同步给从副本。
  • flower 从副本,当主副本宕机时,会在从副本中选举一个作为主副本。
  • controller kafka集群中用来进行选举的一个broker。
  • message 消息主体
  • offset 消费者消费偏移量,由消费者维护,但存储在broker中

所有消息都有一个topic,消费组和topic为多对多关系,topic和分区为一对多关系,consumer 和分区为一对多关系。
生产者发送消息时,并非一条消息发送一次,而是默认等数据到16k或者消息超过10ms时,发送一次。消息到服务端后,会将消息以追加的方式写入文件,os pageCache和顺序io使得写入消息的性能非常高,速度相当于内存写。
消费者拉取数据时,消息从磁盘发送采用sendfile的零拷贝方式,DMA将数据从磁盘读取到内核空间后,将数据的位置、长度等描述符复制到用户空间以及socket缓冲区,然后DMA将数据从内核空间直接传递给引擎协议。
服务端存储数据时,以log追加的方式存储,为了避免数据过大导致的查询时间过长,采用了分片和索引机制,将一个分区分成多个segment,每个segment下存在索引文件与数据文件,索引文件的元数据就是数据文件的偏移地址。每一个分区的文件存在同一个文件夹里面,文件夹命名方式为topic-分区号。索引文件和数据文件的命名方式为该segment的第一个消息的offset。

消息重复与丢失

要做到消息不重复消费,不丢失消息,一般从三个地方入手。生产者 服务端 消费者

生产者

kafka生产者的acks方式有三种:

  • 0 消息发送之后,不等待broker应答
  • -1 消息发送之后,等待leader broker以及其ISR列表(与leader保持同步的follower列表)写入成功,才返回成功
  • 1 默认值,当leader写入成功后,返回成功
    在默认值1中,当集群没有出现问题时,做到了消息不丢失,但可以由于网络原因,生产者重复发送消息导致消息重复。
    kafka0.11版引入了idempotent producer机制,当设置值为true时,broker为每一条消息根据编号去重,以此可以实现生产者的exactly once.
服务端

服务端保证消息不丢失,也就是消息持久化。kafka采用副本的方式来保证消息不丢失。

消费者

消费者靠offset保证消息的传递。
当消费者开启enable.auto.commit时,消费者取到消息后,就自动提交offset。
不开启时,当消息消费完成之后,才会提交,这就保证了消息不会丢失消费,但可能重复消费,这就需要在业务层面来保证消息的幂等性。

RocketMQ

RocketMQ是一个纯Java、分布式、队列模型的开源消息中间件,前身是MetaQ,
是阿里参考Kafka特点研发的一个队列模型的消息中间件,
后开源给apache基金会成为了apache的顶级开源项目,具有高性能、高可靠、高实时、分布式特点。

性能对照表

特性 ActiveMQ RabbitMQ Kafka RocketMQ
开发语言 java erlang scala java
单机吞吐量 万级 万级 10万级(可接近100万) 10万级
时效性 ms级 us级 ms级以内 ms级
可用性 高(主从架构) 高(主从架构) 非常高(分布式架构) 非常高(分布式架构)

你可能感兴趣的:(java-rabbitmq,java-activemq,kafka,java-rocketmq)