消息模型: 主题和队列有什么区别

消息模型的演进

1. 消息队列,最初架构上,就是一个严格FIFO的结构。

消费者 <——接收—— 队列 <——发送—— 生产者

消费者出队操作,删除数据,生产者入队操作。服务端存储消息的地方叫队列。

若有多个生产者,则多生产者自然顺序投递消息到队列。若有多消费者,他们之间则是竞争关系。

若希望消息给每个消费者,即每个消费者都要获取全量消息,比如订单给风控,客服等。

不能采用生产者根据消费者数量复制消息到多队列的做法,浪费存储资源且生产和消费就耦合了。

2.消息队列就演化出发布-订阅模型 (Publish-Describe Pattern)

                               

                                |————订阅——|

发布者 —发布—> 主题  —接收—>  订阅者

                                |      —接收—>  订阅者

                                |————订阅——|

在发布-订阅模型中,消息的发送方是发布者,接收方式订阅者,存储消息的容器叫主题。订阅可以认为是主题在消费时的逻辑副本。

队列模型和发布订阅模型历史上并存,二者最大区别在于一份消息能否被消费多次,现代大多是后者,因为后者功能上兼容前者。

RabbitMQ的消息模型

RabbitMQ是少数仍在使用队列模型的流行产品之一。通过额外的exchange模块去完成消息投放到多队列,以实现多消费者消费。

生产者把消息投递给exchange,exchange基于配置策略决定投递到哪些队列。

RocketMQ的消息模型

RocketMQ是标准的发布-订阅模型(发布者-主题-订阅者)。但是RocketMQ也有队列概念。

起源在于消息队列的生产&消费机制,所有消息队列都用的"请求-确认"机制。

具体就是生产者发送消息到服务端(broker),服务端收到消息后,将消息写入主题或者队列中,并给生产者发送确认的响应。生产者没收到ack就会重试。

消费者收到消息并完成业务逻辑后会返回给服务端消费成功的确认,服务端收到ack认为消息被成功消费,否则会给消费者重发消息直到收到消费端ack。

保证了可靠性,但是对于服务端消息存储容器来说(主题),其中一条被消费前,下一条不会被消费,一定是被有序消费。

因此不可能出现一个主题,一个订阅者可以多个消费端并行消费的情况(服务端不能同时投递)。

为了解决这个问题,每个主题内包含多队列,多队列实现多实例并行生产和消费。队列内有序,主题层面不保证有序。

RocketMQ中的订阅者是消费组Consumer Group。各消费组订阅主题,消费进度独立。

组内则包含多个消费者(提升消费能力),消费者是竞争主题内消息的关系,即一条消息被消费者1消费后组内其他消费者不会再收到。

由于是发布-订阅模型,因此不能消费后删除主题内的消息,而是为每个订阅者(消费组)记录了在主题内每个队列上的offset。

Kafka的消息模型

与rocktmq完全一致,包括生产消费过程中的确认机制。

唯一区别是rocketmq的队列在kafka中被称作分区partition。含义和功能没有区别。

小结

主题和队列对应两个不同的消息模型:队列模型和发布-订阅模型。本质上二者可以变化和拓展来互相替代。

常用消息队列,RabbitMQ是队列模型,但其可以实现发布-订阅模型;kafka和RMQ都是发布-订阅者模型。

本节所说全部都是业务模型,类比关系数据库,业务模型都是二维表,但实现模型MySQL是B+树、HBase是KV结构存储。Kafka和RMQ也一样实现会不同。

思考:如果允许消息空洞,不要求严格有序,如何提升主题的消费能力?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值