主题和队列的区别

Monday, August 5, 2019

主题和队列有什么区别

数据结构中,也有队列,先进先出,这就不多说了。那消息队列其实也是类似,先进先出,就是要保证这些消息严格有序。早期的消息队列,就是按照数据结构队列设计出来的。

但是这样做是有问题的,比如有多个消费者接收同一个队列的消息,这些消费者之间实际上是竞争关系,每个消费者只能收到队列中的一部分消息,任何一个消息只能被其中一个消费者收到。

如果需要将一份消息发给多个消费者,要求每个消费者都能收到全量的消息。这时候单队列模式就满足不了了,一个解决方法是,为每个消费者创建单独的队列,让生产者发送多份。但这么做肯定不切实际,同一份消息被复制到多个队列,浪费资源不说,生产者还必须知道有多少个消费者,使得耦合性非常高,违背了消息队列解耦的设计初衷。

为了解决上述问题,演化出了另一个模型,发布-订阅模型

在这个模型中,发布者将消息放到主题中,订阅者在接收消息之前需要订阅主题,订阅这里即是一个动作,也可以认为是主题在消费时的一个逻辑副本,每份订阅中,订阅者都可以接收到主题的所有消息。

其实,生产者就是发布者,主题就是队列,消费者就是订阅者。没有本质区别,最大的区别就是一份消息能不能被消费多次。

RabbitMQ的消息模型

RabbitMQ依然在使用队列模型,它解决多个消费者的问题是使用他特色的Exchange模块,生产者不关心消息发送给哪个队列,由Exchange上的配置的策略来决定投递到哪里。

RocketMQ的消息模型

RocketMQ使用的是标准的发布-订阅模型。 但是他也有队列这个概念,并且是非常重要的一个概念。 几乎所有的消息队列产品都有“请求-确认”机制,确保消息的准确传递。但是这个机制有一个问题,为了确保消息的有序性,在某一条消息被成功消费前,下一条消息是不能被消费的,否则就违背了有序性的原则。

也就是说,每个主题的任意时刻,至多只能有一个消费者实例在进行消费,那没办法水平扩展消费者的数量来提升消费端总体的消费性能。

RocketMQ在主题下面增加了队列的概念。 每个主题包含多个队列,通过队列来实现多实例并行生产和消费,RocketMQ只在队列上保证消息的有序性,主题层面是无法保证消息的严格顺序的。

订阅者是通过消费组来体现的。每个消费组都消费主题一份完整的消息,不同消费组之间消费进度不受影响,互相独立。

消费组中包含多个消费者,同一个组内的消费者是竞争消费的关系,每个消费者负责消费组内的一部分消息,这个消息被某个消费者消费了,另一个消费者就不会再收到这个消息。

由于消息需要被不同的组进行多次消费,所以消费完的消息并不会立即被删除,这就需要RocketMQ为每个消费组在每个消费队列上维护一个消费位置,前面的都消费过,后面的都没被消费。

Kafka消息模型

与RocketMQ基本一致,唯一的区别是Kafka里面的队列对应的名称是分区,含义和功能是一样的。

消息队列

利用事务消息实现分布式事务

常见的消息队列产品