聊聊消息中间件Push模型和Pull模型优缺点

如题所述

第1个回答  2022-06-07

这篇文章前,先抛出个问题

 
 

简要分析下 Push 和 Pull模型,在不同场景下各自存在的利弊。

对于 Producer 速率大于 Consumer 速率的情况,有两种可能性需要讨论:

Push方式由于无法得知当前 Consumer 的状态( ),所以只要有数据产生,便会不断地进行推送,在以上两种情况下时,可能会导致 Consumer 的负载进一步加重,甚至是崩溃(比如生产者是 flume 疯狂抓日志,消费者是 HDFS+hadoop,处理效率跟不上)。除非Consumer 有合适的反馈机制能够让服务端知道自己的状况。 (也可以 通过消费端限流方案,比如RabbitMQ消费者设置Qos,服务端Borker就会限制对消费端的发送流程,但是这个流量设置就需要衡量,不能太大也不能太小)

而采取 Pull 的方式问题就简单了许多,由于 Consumer 是主动到服务端拉取数据,此时只需要降低自己访问频率就好了。举例:如前端是 flume 等日志收集业务,不断往 CMQ 生产消息,CMQ 往后端投递,后端业务如数据分析等业务,效率可能低于生产者。

Pull 模式有什么问题呢? 由于主动权在消费方,消费方无法准确地决定何时去拉取最新的消息 。如果一次 Pull 取到消息了还可以继续去 Pull,如果没有 Pull 取到消息则需要等待一段时间再重新 Pull。

但等待时间就很难判定了。你可能会说,我可以有 xx 动态拉取时间调整算法 ,但问题的本质在于, 有没有消息到来这件事情决定权不在消费方 。也许 1 分钟内连续来了 1000 条消息,然后半个小时没有新消息产生,可能你的算法算出下次最有可能到来的时间点是31分钟之后,或者 60 分钟之后,结果下条消息 10 分钟后到了,是不是很让人沮丧?

当然也不是说延迟就没有解决方案了,业界较成熟的做法是从短时间开始(不会对 CMQ broker 有太大负担),然后 指数级增长等待 。比如开始等 5ms,然后 10ms,然后 20ms,然后 40ms……直到有消息到来,然后再回到 5ms。即使这样,依然存在延迟问题: 假设 40ms 到 80ms 之间的 50ms 消息到来,消息就延迟了 30ms ,而且对于半个小时来一次的消息,这些开销就是白白浪费的。

在腾讯云的 CMQ 里,有一种优化的做法- 长轮询 ,来平衡 Pull/Push 模型各自的缺点。

在消息系统中,Producer 和 Consumer 是完全解耦的,Producer 发送消息时,并不要求Consumer 一定要在线,对于 Consumer 也是同样的道理,这也是消息通信区别于 RPC 通信的主要特点; 但是对于 Consumer不在线的情况,却有很多值得讨论的场景

参考文章:
1 、 选择 Push 还是 Pull (腾讯消息中间件CMQ技术文档)
2、 RabbitMQ之Consumer消费模式(Push & Pull) (厮大文章,抓包说明Push模型不会等待消费者是否消费完成前一个消息,就会发送第二个消息)。

相似回答