消息中间件简介
1:简介
Message Queue(MQ),消息队列中间件。很多人都说:MQ通过将消息的发送和接受分离来实现应用程序的异步和解耦,这给人的直觉是:MQ是异步的,用来解耦的,但是MQ这个只是效果而不是目的。MQ真正的目的是为了通讯,屏蔽底层复杂的通讯协议,定义了一套应用层的、更加简单的通讯协议。
传统系统中两个模块之间通讯要么是HTTP,要么是自己开发的TCP,这两种协议都是原始的协议,实现起来很困难。
MQ定义了两个对象:发送数据的叫生产者,接受数据的叫消费者。它提供一个SDK让我们可以定义自己的生产者和消费者实现消息通讯而无视底层通讯协议。
2:分类
1.1:有Broker(代理中间件)的MQ
这个流派通常有一台服务器作为Broker,所有的消息都通过它中转。生产者把消息发送给它就结束自己的任务了,Broker则把消息主动推送给消费者(或者消费者主动轮询)。
有Broker的又分为两种:
1.1.1 重Topic
kafka、JMS(ActiveMQ,升级版RecketMQ)就属于这个流派,生产者会发送key和数据到Broker,由Broker比较key之后决定给哪个消费者。这种模式是最常见的模式,使我们对MQ最多的印象。Topic某种意义上就是queue(先进先出的缓存策略)。
虽然架构一样,但是kafka的性能要比jms的性能不知道高多多少倍,所以基于这种类型的MQ只有kafka一种备选方案。如果你需要一条暴力的数据流(在乎性能而不在乎灵活性),那么kafka是最好的选择(性能好,但有可能丢包,一般用于传不那么重要且数据量大的数据)。
Kafka速度的秘诀在于,它把所有的消息都变成一个的文件。通过mmap提高I/O速度,写入数据的时候它是末尾添加所以速度最优;读取数据的时候配合sendfile直接暴力输出
1.1.2 轻Topic
这种的代表是RabbitMQ(或者说AMQP)。生产者发送key和数据,消费者定义订阅的队列,Broker收到数据后会通过一定的逻辑计算出key对应的队列,然后把数据交给队列。
这种模式下解耦了key和queue,在这种架构中queue是非常轻量级的(在RabbitMQ中它的上线取决于你的内存),消费者关心的只是自己的queue,生产者不必关心数据最终给谁了,只要指定key就行了,中间的那层映射在AMQP中叫exchange(交换机)。这个中间商不赚差价!
AMQP中有四种exchange:
- Direct exchange:key等于queue
- Fanout exchange:无视key,给所有的queue都来一份
- Topic exchange:key可以用“宽字符”模糊匹配queue
- Headers exchange:无视key,通过查看消息头部元数据来决定发给哪个queue(AMQP头部元数据非常丰富,且可以自定义)
这种结构的架构给通讯带来了很大的灵活性,我们能先到的通讯方式都可以用这四种exchange表达出来。如果你需要有一个企业数据总线(在乎灵活性),那么RabbitMQ绝对是值得一用的。
1.2:无Broker的MQ
无Broker的MQ代表是ZeroMQ。
节点之间通讯的消息都是发送到批次的队列中,每个节点都既是生产者也是消费者。ZeroMQ做的事情就是封装出一套类似Socket的API可以完成发送数据、读取数据。
ZeroMQ其实就是一个跨语言的、重量级的Actor模型的邮箱库。你可以把自己的程序想象成一个Actor,ZeroMQ就是提供邮箱功能的库;ZeroMQ可以实现同一台机器的RPC通讯业可以实现不同机器的TCP、UDP通讯,如果你需要一个强大的、灵活的、野蛮的通讯能力,ZeroMQ会是一个很好的选择。
3、几大MQ产品的比较
常见的MQ产品包括Kafka、RabbitMQ、RocketMQ。
优点 | 缺点 | 使用场景 | |
---|---|---|---|
Kafka | 吞吐量非常大、性能非常好、集群高可用 | 会丢数据、功能比较单一 | 日志分析、大数据采集 |
RabbitMQ | 消息可靠性高、功能全面 | 吞吐量比较低、消息积累会影响性能、erlang语言不好定制 | 小规模场景 |
RocketMQ | 高吞吐、高性能、高可用、功能全面 | 开源功能不如云上版、官方文档比较简单、客户端只支持java | 几乎全场景 |