好的架构不是设计出来的,而是演进出来的。
MQ 准确的名字是消息引擎系统。根据维基百科的定义,消息引擎系统是一组规范。企业利用这组规范在不同系统之间传递语义准确的消息,实现松耦合的异步式数据传递。
消息引擎系统的作用是“削峰填谷”,所谓的“削峰填谷”就是指缓冲上下游瞬时突发流量,使其更平滑。特别是对于那种发送能力很强的上游系统,如果没有消息引擎的保护,“脆弱”的下游系统可能会直接被压垮导致全链路服务“雪崩”。但是,一旦有了消息引擎,它能够有效地对抗上游的流量冲击,真正做到将上游的“峰”填满到“谷”中,避免了流量的震荡。
消息引擎系统的另一大好处在于发送方和接收方的松耦合,这也在一定程度上简化了应用的开发,减少了系统间不必要的交互。
使用场景
异步处理
异步处理可以更快地返回结果。减少等待,自然实现了步骤之间的并发,提升系统总体的性能。
服务解耦
当调用方需要关心执行结果,通常使用RPC调用。但当调用方不关心执行结果,却仍然使用RPC调用,则会引发上下游极大的耦合与瓶颈。如果使用消息队列,只需要关心消息是否送达了队列,至于谁希望订阅,接下来收到消息如何处理,是下游的事情,这样就实现了异步通信和应用解耦,实现复杂逻辑的拆分。
流量控制
在诸如秒杀、抢红包等大型活动时会带来很高的瞬时流量,如果没做相应的保护,往往导致下游存储压力过大,发生雪崩进而导致服务不可用,或者直接通过限流则会导致大量请求失败用户体验差。可以通过消息队列 MQ 来进行流量消峰,保护下游。
消息队列产品
2011 年初,Linkin 开源了 Kafka 这个优秀的消息中间件,淘宝中间件团队在对 Kafka 做过充分 Review 之后,被 Kafka 无限消息堆积,高效的持久化速度吸引,但是同时发现这个消息系统主要定位于日志传输,对于使用在商品交易、订单、充值等场景下还有诸多特性不满足,为此重新用 Java 语言编写了 RocketMQ,定位于非日志的可靠消息传输。
- RocketMQ:主要应用于高可用和低延迟线上业务
- Kakfa:主要应用于高吞吐的流式任务(近在线)和离线任务
RabbitMQ
RabbitMQ 是使用一种比较小众的编程语言:Erlang 语言编写的,它最早是为电信行业系统之间的可靠通信设计的,也是少数几个支持 AMQP 协议的消息队列之一。
RabbitMQ 是一个相当轻量级的消息队列,非常容易部署和使用。
RabbitMQ 是一个比较有特色的功能是支持非常灵活的路由配置,和其他消息队列不同的是,它在生产者(Producer)和队列(Queue)之间增加了一个 Exchange 模块,可以理解为交换机。这个 Exchange 模块的作用和交换机也非常相似,根据配置的路由规则将生产者发出的消息分发到不同的队列中。路由的规则也非常灵活,甚至可以自己来实现路由规则。基于这个 Exchange,可以产生很多的玩儿法,如果正好需要这个功能,RabbitMQ 是个不错的选择。
接下来说下 RabbitMQ 的几个问题:
- 第一个问题是,RabbitMQ 对消息堆积的支持并不好,在它的设计理念里面,消息队列是一个管道,大量的消息积压是一种不正常的情况,应当尽量去避免。当大量消息积压的时候,会导致 RabbitMQ 的性能急剧下降。
- 第二个问题是,RabbitMQ 的性能是介绍的这几个消息队列中最差的,根据官方给出的测试数据,依据硬件配置的不同,它大概每秒钟可以处理几万到十几万条消息。其实,这个性能也足够支撑绝大多数的应用场景了,不过,如果你的应用对消息队列的性能要求非常高,那不要选择 RabbitMQ。
- 最后一个问题是 RabbitMQ 使用的编程语言 Erlang,这个编程语言不仅是非常小众的语言,更麻烦的是,这个语言的学习曲线非常陡峭。
Kafka
Kafka与周边生态系统的兼容性是最好的没有之一,尤其在大数据和流计算领域,几乎所有的相关开源软件系统都会优先支持Kafka。
Kafka使用Scala和Java语言开发,设计上大量使用了批量和异步的思想,这种设计使得Kafka能做到超高的性能。Kafka的性能,尤其是异步收发的性能,是三者中(RabbitMQ、RocketMQ)最好的,但与RocketMQ并没有量级上的差异,大约每秒钟可以处理几十万条消息。
但是 Kafka 这种异步批量的设计带来的问题是,它的同步收发消息的响应时延比较高,因为当客户端发送一条消息的时候,Kafka 并不会立即发送出去,而是要等一会儿攒一批再发送,在它的 Broker 中,很多地方都会使用这种“先攒一波再一起处理”的设计。当业务场景中,每秒钟消息数量没有那么多的时候,Kafka 的时延反而会比较高。所以,Kafka 不太适合在线业务场景。
如果需要处理海量的消息,像收集日志、监控信息或是前端的埋点这类数据,或是应用场景大量使用了大数据、流计算相关的开源产品,那 Kafka 是最适合的消息队列。
RocketMQ
RocketMQ 对在线业务的响应时延做了很多的优化,大多数情况下可以做到毫秒级的响应,如果应用场景很在意响应时延,那应该选择使用 RocketMQ。
RocketMQ 的性能比 RabbitMQ 要高一个数量级,每秒钟大概能处理几十万条消息。
如果系统使用消息队列主要场景是处理在线业务,比如在交易系统中用消息队列传递订单,那 RocketMQ 的低延迟和金融级的稳定性是需要的。