消息队列
之前有听到很多开发同事,一提到MQ就说是消息队列,其实这二者不是等同的。
早期的消息队列确实是基于队列的思想去设计的,我们知道队列是一种先进先出的数据结构,那么在消息队列里:
- 发送消息就叫入队列
- 消费消息就叫出队列
简单来说就是如下这个过程:
这里消费意味着消息从队列里删除了,那么倘若有多个消费者消费这个队列的话,那么每个消费者之间就存在着竞争关系,同一条消息不会被多个消费者所消费,每个消费者呢只会消费该队列里部分消息。那么如何让每个消费者消费全量消息呢?
大家很自然想到了,消息冗余啊。同一份消息分别保存到不同的队列,这样每个消费者就可以各自消费全量的消息了。目前这种设计的代表是rabbitmq。
队列模型
rabbitmq是基于队列模型来设计的,它的生产和消费过程如图:
- producer发送消息到某种交换机
- 一个或多个队列通过routing key跟交换机进行绑定
- 交换机将消息路由分发到匹配routing key的队列存储
- 消费者订阅某个队列进行消费,消费完成后从队列里删除消息
rabbitmq有四种交换机,分别为:
- 直连交换机
- 扇形交换机
- 主题交换机
- 头部交换机 rabbitmq通过其中的主题交换机或扇形交换机来实现类似发布-订阅模型(下面会讲),同一份消息如果需要被多个消费者来消费,需要配置 Exchange 将消息发送到多个队列,每个队列中都存放一份完整的消息数据。
发布-订阅模型
以kafka和rocketmq为代表的mq是基于发布-订阅模型来设计的,下面给出一张图方便理解这种模型的消息发送和消费过程:
对比下rabbitmq,在设计上这二者与其还是有很大不同的:
- 生产者和消费者有组的概念
- 发送和消费消息需要指定Topic、tag,可根据tag来区分不同类型的业务消息
- 一个Topic可以包含多个queue,这里的queue跟rabbitmq中的队列不是一回事,是分区的概念(rocketmq里叫queue,kafka里叫分区)。一个Topic可以包含多个分区,消息会被均衡的存储到不同的分区
- 在一个消费组里,一个分区只能由一个消费者消费。而rabbitmq中一个队列可以有多个消费者共同消费
- Topic中消息只会保存一份,多个订阅者可以分别订阅它,消费完并不会立马删除,而是记录消费的偏移量offset,下次消费从上次消费的offset接着拉消息消费。而rabbitmq消费完就删除了
后续我会开始写RocketMq系列文章,还请多多支持!