关于 MQ 的定义

Message QueueMQ)消息队列中间件,通常我们在网上看到的对其定义是将消息的发送和接受分离来实现应用程序的异步和解耦,给人的直觉是 MQ 是异步的,用来解耦的。但这个只是 MQ 的效果,而不是目的。MQ 真正的目的是为了通讯,屏蔽底层复杂的通讯协议,定义了一套应用层上更加简单的通讯协议。

一套分布式系统中两个模块之间通讯要么是 HTTP,要么是 TCP,但这两种协议其实都是原始的协议。前者实现通讯就必须要做到各客户端都有 WebServer,而且不支持长连接;后者就更加原始了 — 粘包、心跳、私有的协议。

MQ 所要做就是在基于这些现有的协议之上构建一个更简单的通讯(生产者/消费者)模型。它定义了两个对象 —发送数据的叫生产者,接受数据的叫消费者,提供一个 SDK 给我们自己定义生产者和消费者实现消息通讯,且无视底层通讯协议。

带 Broker 的流派

这个流派通常有一台服务器作为 Broker,所有的消息都通过它进行中转。生产者把消息发送给它就结束自己的任务了,最后 Broker 则把消息主动推送给消费者(或者消费者主动轮询)。

重 Topic 的 MQ

KafkaActive MQ 就属于这个流派:生产者发送 key 和数据到 Broker,由 Broker 比较 key 之后决定给哪个消费者。

谈谈消息队列的流派

在这种模式下,Topic(主题消息) 往往是一个比较大的概念,甚至一个系统中就可能只有一个 Topic

虽然这两种消息队列的架构一样,但是 Kafka 的性能要比 Active MQ 的性能不知道高到多少倍,所以基本这种类型的 MQ 只有 Kafka一种备选方案。

轻 Topic 的 MQ

这种的代表是 RabbitMQAMQP)。生产者发送 key 和数据,Borker 收到数据之后会根据 key 通过一定的逻辑计算出相应的队列,最后消费者订阅队列。

谈谈消息队列的流派

在这种架构中 Queue 是非常轻量级的(在 RabbitMQ 中它的上限取决于你的内存),消费者关心的只是自己的 Queue;生产者不必关心数据最终给谁,只要指定 key 就行了。中间的那层映射在 AMQP 中叫 exchange(交换机)

AMQP 中有四种 exchange

  • Direct exchangekey 等于 queue
  • Fanout exchange:无视 key,给所有的 queue 都来一份。
  • Topic exchangekey 可以用 “宽字符” 模糊匹配 queue
  • Headers exchange:无视 key,通过查看消息的头部元数据来决定发给哪个 queue

这种架构给通讯带来了极大的灵活性,我们能想到的通讯方式都可以用这四种 exchange 表达出来。

不带 Broker 的流派

ZeroMQ

不带 BrokerMQ 代表就是 ZeroMQ。可以说是解决通讯问题的更高级 Socket,它被设计成了一个 “库” 而不是一个中间件,这种实现也可以达到没有 Broker 的目的。

谈谈消息队列的流派

各节点之间的通讯都是发送到彼此的队列中,每个节点即是生产者也是消费者。类似于一套 SocketAPI,可以完成发送和读取数据。