rabbitmq 和 kafka 消息模型的区别以及 rabbitmq 的若干知识点

RabbitMQ kafka amqp

Posted by gomyck on June 21, 2023

RabbitMQ和Kafka都是基于 发布/订阅 模式的消息中间件,但是他们在消息存储和消费的方式上有一些区别。

RabbitMQ的消息模型是基于 队列 的,每个消息只能被一个消费者消费,除非使用 fanout 交换器来实现广播。RabbitMQ会在消费者 确认 消息后删除消息,如果没有确认,消息会重新进入队列等待其他消费者消费。

Kafka的消息模型是基于 分区 的,每个分区可以有多个消费者消费,但是每个消费者只能消费一个分区。Kafka不会在消费者消费消息后删除消息,而是根据配置的 保留时间 或 保留大小 来定期删除过期的消息。Kafka会为每个消费者维护一个 偏移量 ,记录消费者已经消费到哪个位置,这个偏移量可以保存在 Zookeeper 或 Kafka 上。

因此,RabbitMQ没有偏移量的概念,而Kafka有。Kafka消费之后不删除是为了支持多个消费者同时消费同一个分区,以及支持重复消费或跳过消费某些消息的场景。

RabbitMQ的消息可靠性是指保证消息不丢失,不重复,不错乱的能力。RabbitMQ可以使用 事务 , confim , 持久化 等机制保障消息的可靠性。

  • 事务机制是指生产者或消费者在发送或接收消息时,可以开启一个事务,然后执行一系列的操作,最后提交或回滚事务。如果事务提交成功,那么消息就被确认;如果事务回滚或失败,那么消息就被拒绝或重新投递。
  • confim机制是指生产者在发送消息时,可以设置一个回调函数,当RabbitMQ收到消息并持久化后,会给生产者发送一个确认消息。这样生产者就可以知道消息是否成功到达RabbitMQ,并且可以对未确认的消息进行重发或其他处理。
  • 持久化机制是指将交换器、队列、消息等保存到磁盘上,以防止RabbitMQ宕机或重启时丢失数据。持久化机制需要在创建交换器和队列时设置 durable 参数为 true ,并且在发送消息时设置 delivery_mode 参数为 2 。

RabbitMQ的高可用性是指保证RabbitMQ在出现故障或异常时,仍然能够正常提供服务的能力。RabbitMQ可以使用 集群 , 镜像队列 , 负载均衡 等机制保障高可用性。

  • 集群机制是指将多台RabbitMQ服务器组成一个集群,形成一个逻辑Broker。集群中的每个节点都可以接收请求,并且集群中的元数据(交换器、队列、绑定等)会在所有节点之间同步。但是集群中的消息不会自动同步,需要使用镜像队列来实现。
  • 镜像队列机制是指将同一个队列的所有数据(元数据和消息)复制到多个节点上,形成镜像。这样当某个节点出现故障时,其他节点仍然可以提供服务,并且保证数据一致性。镜像队列需要在创建队列时设置 x-ha-policy 参数为 all 或者指定一些节点。
  • 负载均衡机制是指使用一些工具(如HAProxy、Nginx等)来分发请求到不同的RabbitMQ节点上,以提高性能和容错能力。负载均衡可以根据不同的策略(如轮询、权重、最少连接等)来选择合适的节点。

RabbitMQ的消息分发机制是指RabbitMQ如何将一个队列中的消息发送给多个消费者的方式。RabbitMQ默认采用 轮询 的方式,即按照顺序依次将每个消息发送给每个消费者,不考虑每个消费者的处理能力和任务时长。RabbitMQ还可以使用 公平分发 的方式,即按照每个消费者的处理能力和任务时长来分配消息。

如果一个队列被多个消费者订阅,那么消息是如何被消费的呢?答案是,每个消息只能被一个消费者消费,除非使用 fanout 交换器来实现广播。

如果想要实现一个队列对应一个消费者,或者保证消息的顺序消费,可以使用以下方法:

  • 在创建队列时设置 exclusive 参数为 true ,表示该队列是排他的,只能被一个消费者订阅。
  • 在创建消费者时设置 autoAck 参数为 false ,表示关闭自动确认机制,让消费者在处理完消息后手动发送确认消息给RabbitMQ。
  • 在创建消费者时设置 prefetchCount 参数为 1 ,表示每个消费者一次只能处理一个消息,直到确认后才能接收下一个消息。
  • 在创建交换器和队列时设置 durable 参数为 true ,表示将交换器和队列持久化到磁盘上,防止RabbitMQ重启或宕机时丢失数据。