日期: April 11, 2022
现在kafka和rabbitmq几乎属于必备用品了,但当我反问自己为什么要用这些东西,为什么有时候用kafka有时候又用rabbitmq时,我却懵了,只是我来之前就在使用了,却没有想过为什么,我告诫自己,一切不要觉得理所应当,所以就有了关于此的自我提问:同样作为消息队列的功能,kafka和rabbitmq如何对比
消息队列在功能维度需求上如下
优先级队列:优先级高的队列先被消费,(倘若消费速度远大于生产速度且boker没有堆积,优先队列也就没有意义了)
延迟队列:延迟队列对应延迟消息,指消息发送后并不想立即被消费,在等待特定时间后才能被消费,延迟队列一般分为两种:基于消息的延迟和基于队列的延迟。
死信队列:为了保证因为某些意外无法被消费的数据不被丢弃,将其推送到死信队列,对应的还有回退队列
重试队列:与回退队列不同的是重试队列一般分成多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大。举个例子:消息第一次消费失败入重试队列 Q1,Q1 的重新投递延迟为 5s,在 5s 过后重新投递该消息;如果消息再次消费失败则入重试队列 Q2,Q2 的重新投递延迟为 10s,在 10s 过后再次投递该消息。以此类推,重试越多次重新投递的时间就越久,为此需要设置一个上限,超过投递次数就入死信队列。
消费模式:分为推和拉,推是broker将消息推至消费端,实时性能较好,但容易推垮消费端,拉是消费方主动去broker拉取消息,实时性下降,但可根据自身能力消费
广播消费:
消息传递模式分两种:点对点和发布/订阅模式
点对点:消息被消费以后,队列中不会再存储,所以消息消费者不可能消费到已经被消费的消息。虽然队列可以支持多个消费者,但是一条消息只会被一个消费者消费
发布订阅:消息先发布到主题(Topic),消费者从主题订阅消息,一条消息可以被多个消费者消费,发布订阅在一对多广播时采用。rabbitmq是典型的点对点模式;kafka是典型的发布订阅模式,但rabbitmq也可设置交换机类型实现发布订阅模式,kafka也能以点对点的形式消费,但kafka有消息回溯功能
**消息回溯:指消息被消费后还可以被消费到
**消息堆积+持久化:通过消息堆积实现流量削峰,分为内存式堆积和磁盘式堆积,rabbitmq是内存式堆积,kafka是磁盘式堆积,但mq在满足条件后也会落盘
***消息幂等性:***at most once:最多一次 消息可能丢失但不会重复;at last once:最少一次,消息一定不会丢失但可能重复;exactly once: 精确一次
此外还有
多租户
多协议支持
流量控制
消息顺序性
安全机制
那么两者之间的对比如下
- kafka不支持优先级队列/延迟队列/死信队列/重试队列,rabbitmq支持
- kafka消费模式为拉,rabbitmq消费模式为推+拉模式
- kafka和rabbitmq均支持广播消费,但建议广播模式使用kafka,它是专业的
- kafka可以根据offset和timestamp进行消息回溯,但rabbitmq中的消息被消费后则会被标记为删除
- 在消息堆积的情况下,kafka的堆积效率远高于rabbitmq,毕竟kafka的数据是直接存磁盘的,而rabbitmq是放内存的
- 流量控制方面,kafka可以通过主动设置将流控作用于生产者或消费者,而rabbitmq的流控则是被动的保护机制,且作用于生产者
- 消息幂等性支持,kafka支持单生产者单分区单会话的幂等性,rabbitmq不支持,它无法保证不重复发送消息
这里涉及一个流控和消息幂等性的概念,后续补充
注:一般 RabbitMQ 的单机 QPS 在万级别之内,而 Kafka 的单机 QPS 可以维持在十万级别,甚至可以达到百万级
所以回到最开始的问题,当我需要一个消息队列时,使用kafka or rabbitmq有区别吗?
rabbitmq本身就是一个开箱即用的消息队列,我们可以让生产者创建一个交换机,然后一个消费者过来订阅这个交换机并创建一个队列,这样一条路就建起来了
kafka本身没有队列的概念,kafka叫topic,当然kafka可以建一个topic,这个topic和拥有一个消费者的消费组进行关联,这样就模拟了一个队列
所以仅作为消息队列的话,仍然建议rabbitmq,毕竟它可以原生的干这个的,且速度上而言,rabbitmq是us级,kafka是ms级,kafka有一个先落盘的过程,虽然rabbitmq开启持久化也会落盘,但内存中也会有一份自然快了一个级别(持久化的消息会同时在内存和磁盘保留一份)
如果是发布/订阅模式,这是kafka在行的,对于大量消息的堆积,rabbitmq完全比不上kafka,因为rabbitmq的消息堆积可是占内存的,可能堆着堆着就崩了