Kafka、ActiveMQ、RabbitMQ和RocketMQ都有哪些区别?

典型回答 Kafka、ActiveMQ、RabbitMQ和RocketMQ都是常见的消息中间件,它们都提供了高性能、高可用、可扩展的消息传递机制,但它们之间也有以下一些区别: 消息传递模型:Kafka主要支持发布-订阅模型,ActiveMQ、RabbitMQ和RocketMQ则同时支持点对点和发布-订阅两种模型。 性能和吞吐量:Kafka在数据处理和数据分发方面表现出色,可以处理每秒数百万条消息,而ActiveMQ、RabbitMQ和RocketMQ的吞吐量相对较低。 消息分区和负载均衡:Kafka将消息划分为多个分区,并分布在多个服务器上,实现负载均衡和高可用性。ActiveMQ、RabbitMQ和RocketMQ也支持消息分区和负载均衡,但实现方式不同,例如RabbitMQ使用了一种叫做Sharding的机制。 开发和部署复杂度:Kafka相对比较简单,易于使用和部署,但在实现一些高级功能时需要进行一些复杂的配置。ActiveMQ、RabbitMQ和RocketMQ则提供了更多的功能和选项,也更加灵活,但相应地会增加开发和部署的复杂度。 社区和生态:Kafka、ActiveMQ、RabbitMQ和RocketMQ都拥有庞大的社区和完善的生态系统,但Kafka和RocketMQ目前的发展势头比较迅猛,社区活跃度也相对较高。 功能支持: #### 优先级队列 延迟队列 死信队列 #### 重试队列 消费模式 事务消息 Kafka 不支持 不支持,可以间接实现延迟队列 无 不直接支持,可以通过消费者逻辑来实现重试机制。 主要是拉模式。 支持事务,但限于消息生产。 RocketMQ 支持 直接支持延迟队列,可以设定消息的延迟时间。 支持 支持重试队列,可以自动或手动将消息重新发送。 支持推和拉两种模式。 支持事务消息。 RabbitMQ 支持 支持延迟队列,可以通过插件或者消息TTL和死信交换来实现。 支持 可以实现重试机制,但需要通过消息属性和额外配置来手动设置。 主要是推模式,但也可以实现拉模式。 支持基本的消息事务。 ActiveMQ 支持 支持 支持 支持重试机制,可以配置消息重发策略。 支持推和拉两种模式。 支持事务消息。 总的来说,这些消息中间件都有自己的优缺点,选择哪一种取决于具体的业务需求和系统架构。 ...

March 22, 2026 · 1 min · santu

Kafka如何保证消息不丢失?

典型回答 Kafka作为一个消息中间件,他需要结合消息生产者和消费者一起才能工作,一次消息发送包含以下是三个过程: 1)Producer 端发送消息给 Kafka Broker 。 2)Kafka Broker 将消息进行同步并持久化数据。 3)Consumer 端从Kafka Broker 将消息拉取并进行消费。 Kafka只对已提交的消息做最大限度的持久化保证不丢失,但是没办法保证100%。 为什么Kafka没办法100%保证消息不丢失? 但是,Kafka还是提供了很多机制来保证消息不丢失的。要想知道Kafka如何保证消息不丢失,需要从生产者、消费者以及kafka集群三个方面来分析。 Producer 消息的生产者端,最怕的就是消息发送给Kafka集群的过程中失败,所以,我们需要有机制来确保消息能够发送成功,但是,因为存在网络问题,所以基本没有什么办法可以保证一次消息一定能成功。 所以,就需要有一个确认机制来告诉生产者这个消息是否有发送成功,如果没成功,需要重新发送直到成功。 我们通常使用Kafka发送消息的时候,通常使用的producer.send(msg)其实是一种异步发送,发送消息的时候,方法会立即返回,但是并不代表消息一定能发送成功。(producer.send(msg).get() 是同步等待返回的。) 那么,为了保证消息不丢失,通常会建议使用**producer.send(msg, callback)**方法,这个方法支持传入一个callback,我们可以在消息发送时进行重试。 同时,我们也可以通过给producer设置一些参数来提升发送成功率: 1 2 3 acks=-1 // 表示 Leader 和 Follower 都接收成功时确认;可以最大限度保证消息不丢失,但是吞吐量低。 retries=3 // 生产端的重试次数 retry.backoff.ms = 300 //消息发送超时或失败后,间隔的重试时间 acks = 0: 表示Producer请求立即返回,不需要等待Leader的任何确认。这种方案有最高的吞吐率,但是不保证消息是否真的发送成功。 acks = -1: 表示分区Leader必须等待消息被成功写入到所有的ISR副本(同步副本)中才认为Producer请求成功。这种方案提供最高的消息持久性保证,但是理论上吞吐率也是最差的。 acks = 1: 表示Leader副本必须应答此Producer请求并写入消息到本地日志,之后Producer请求被认为成功。如果此时Leader副本应答请求之后挂掉了,消息会丢失。这个方案,提供了不错的持久性保证和吞吐。 Broker Kafka的集群有一些机制来保证消息的不丢失,比如复制机制、持久化存储机制以及ISR机制。 持久化存储:Kafka使用持久化存储来存储消息。这意味着消息在写入Kafka时将被写入磁盘,这种方式可以防止消息因为节点宕机而丢失。 ISR复制机制:Kafka使用ISR机制来确保消息不会丢失,Kafka使用复制机制来保证数据的可靠性。每个分区都有多个副本,副本可以分布在不同的节点上。当一个节点宕机时,其他节点上的副本仍然可以提供服务,保证消息不丢失。 在服务端,也有一些参数配置可以调节来避免消息丢失: 1 2 3 replication.factor //表示分区副本的个数,replication.factor >1 当leader 副本挂了,follower副本会被选举为leader继续提供服务。 min.insync.replicas //表示 ISR 最少的副本数量,通常设置 min.insync.replicas >1,这样才有可用的follower副本执行替换,保证消息不丢失 unclean.leader.election.enable = false //是否可以把非 ISR 集合中的副本选举为 leader 副本。 Consumer 作为Kafka的消费者端,只需要确保投递过来的消息能正常消费,并且不会胡乱的提交偏移量就行了。 ...

March 22, 2026 · 1 min · santu

Kafka怎么保证消费只消费一次的_

典型回答 Kafka消息只消费一次,这个需要从多方面回答,既包含Kafka自身的机制,也需要考虑客户端自己的重复处理。 可以从以下几个方面回答: 首先,在Kafka中,每个消费者都必须加入至少一个消费者组。同一个消费者组内的消费者可以共享消费者的负载。因此,如果一个消息被消费组中的任何一个消费者消费了,那么其他消费者就不会再收到这个消息了。 另外,消费者可以通过手动提交消费位移来控制消息的消费情况。通过手动提交位移,消费者可以跟踪自己已经消费的消息,确保不会重复消费同一消息。 还有就是客户端自己可以做一些幂等机制,防止消息的重复消费。 ✅如何解决接口幂等的问题? 另外可以借助Kafka的Exactly-once消费语义,其实就是引入了事务,消费者使用事务来保证消息的消费和位移提交是原子的,而生产者可以使用事务来保证消息的生产和位移提交是原子的。Exactly-once消费语义则解决了重复问题,但需要更复杂的设置和配置。 扩展知识 Kafka的三种消息传递语义 在Kafka中,有三种常见的消息传递语义:At-least-once、At-most-once和Exactly-once。其中At-least-once和Exactly-once是最常用的。 At-least-once消费语义 At-least-once消费语义意味着消费者至少消费一次消息,但可能会重复消费同一消息。在At-least-once语义中,当消费者从Kafka服务器读取消息时,消息的偏移量会被记录下来。一旦消息被成功处理,消费者会将位移提交回Kafka服务器。如果消息处理失败,消费者不会提交位移。这意味着该消息将在下一次重试时再次被消费。 At-least-once语义通常用于实时数据处理或消费者不能容忍数据丢失的场景,例如金融交易或电信信令。 Exactly-once消费语义 Exactly-once消费语义意味着每个消息仅被消费一次,且不会被重复消费。在Exactly-once语义中,Kafka保证消息只被处理一次,同时保持消息的顺序性。为了实现Exactly-once语义,Kafka引入了一个新的概念:事务。 事务是一系列的读写操作,这些操作要么全部成功,要么全部失败。在Kafka中,生产者和消费者都可以使用事务,以保证消息的Exactly-once语义。具体来说,消费者可以使用事务来保证消息的消费和位移提交是原子的,而生产者可以使用事务来保证消息的生产和位移提交是原子的。 在Kafka 0.11版本之前,实现Exactly-once语义需要一些特殊的配置和设置。但是,在Kafka 0.11版本之后,Kafka提供了原生的Exactly-once支持,使得实现Exactly-once变得更加简单和可靠。 总之,At-least-once消费语义保证了数据的可靠性,但可能会导致数据重复。而Exactly-once消费语义则解决了重复问题,但需要更复杂的设置和配置。选择哪种消费语义取决于业务需求和数据可靠性要求。

March 22, 2026 · 1 min · santu

Kafka 几种选举过程简单介绍一下?

典型回答 Kafka 中常见的选举过程有以下几种: Partition Leader 选举 Kafka 中的每个 Partition 都有一个 Leader,负责处理该 Partition 的读写请求。在正常情况下,Leader 和 ISR 集合中的所有副本保持同步,Leader 接收到的消息也会被 ISR 集合中的副本所接收。当 leader 副本宕机或者无法正常工作时,需要选举新的 leader 副本来接管分区的工作。 Leader 选举的过程如下: 每个参与选举的副本会尝试向 ZooKeeper 上写入一个临时节点,表示它们正在参与 Leader 选举; 所有写入成功的副本会在 ZooKeeper 上创建一个序列号节点,并将自己的节点序列号写入该节点; 节点序列号最小的副本会被选为新的 Leader,并将自己的节点名称写入 ZooKeeper 上的 /broker/…/leader 节点中。 Controller 选举 Kafka 集群中只能有一个 Controller 节点,用于管理分区的副本分配、leader 选举等任务。当一个Broker变成Controller后,会在Zookeeper的/controller节点 中记录下来。然后其他的Broker会实时监听这个节点,主要就是避免当这个controller宕机的话,就需要进行重新选举。 Controller选举的过程如下: 所有可用的 Broker 向 ZooKeeper 注册自己的 ID,并监听 ZooKeeper 中 /controller 节点的变化。 当 Controller 节点出现故障时,ZooKeeper 会删除 /controller 节点,这时所有的 Broker 都会监听到该事件,并开始争夺 Controller 的位置。 为了避免出现多个 Broker 同时竞选 Controller 的情况,Kafka 设计了一种基于 ZooKeeper 的 Master-Slave 机制,其中一个 Broker 成为 Master,其它 Broker 成为 Slave。Master 负责选举 Controller,并将选举结果写入 ZooKeeper 中,而 Slave 则监听 /controller 节点的变化,一旦发现 Master 发生故障,则开始争夺 Master 的位置。 当一个 Broker 发现 Controller 失效时,它会向 ZooKeeper 写入自己的 ID,并尝试竞选 Controller 的位置。如果他创建临时节点成功,则该 Broker 成为新的 Controller,并将选举结果写入 ZooKeeper 中。 其它的 Broker 会监听到 ZooKeeper 中 /controller 节点的变化,一旦发现选举结果发生变化,则更新自己的元数据信息,然后与新的 Controller 建立连接,进行后续的操作。 扩展知识 kafka选举中,为什么节点序列号最小的副本会被选为新的 Leader 在Kafka中,节点序列号最小的副本被选为新的Leader是因为Kafka使用了ZooKeeper作为其协调服务。在Kafka集群中,ZooKeeper负责维护集群的元数据(例如主题和分区信息)以及Brokers(Kafka服务器)的状态。 ...

March 22, 2026 · 1 min · santu

Kafka如何实现顺序消费?

典型回答 Kafka的消息是存储在指定的topic中的某个partition中的。并且一个topic是可以有多个partition的。同一个partition中的消息是有序的,但是跨partition,或者跨topic的消息就是无序的了。 为什么同一个partition的消息是有序的? 因为当生产者向某个partition发送消息时,消息会被追加到该partition的日志文件(log)中,并且被分配一个唯一的 offset,文件的读写是有顺序的。而消费者在从该分区消费消息时,会从该分区的最早 offset 开始逐个读取消息,保证了消息的顺序性。 基于此,想要实现消息的顺序消费,可以有以下几个办法: 1、在一个topic中,只创建一个partition,这样这个topic下的消息都会按照顺序保存在同一个partition中,这就保证了消息的顺序消费。 2、发送消息的时候指定partition,如果一个topic下有多个partition,那么我们可以把需要保证顺序的消息都发送到同一个partition中,这样也能做到顺序消费。 扩展知识 如何发到同一个partition 当我们发送消息的时候,如果key为null,那么Kafka 默认采用 Round-robin 策略,也就是轮转,实现类是 DefaultPartitioner。那么如果想要指定他发送到某个partition的话,有以下三个方式: 指定partition 我们可以在发送消息的时候,可以直接在ProducerRecord中指定partition 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.ProducerRecord; import java.util.Properties; public class KafkaProducerExample { public static void main(String[] args) { // 创建Kafka生产者 Producer<String, String> producer = new KafkaProducer<>(getProperties()); String topic = "hollis_topic"; // 指定要发送消息的主题 String message = "Hello World!"; // 要发送的消息内容 int partition = 0; // 要发送消息的分区 // 创建包含分区信息的ProducerRecord ProducerRecord<String, String> record = new ProducerRecord<>(topic, partition, null, message); // 发送消息 producer.send(record); // 关闭Kafka生产者 producer.close(); } } 指定key 在没有指定 Partition(null 值) 时, 如果有 Key, Kafka 将依据 Key 做hash来计算出一个 Partition 编号来。如果key相同,那么也能分到同一个partition中: ...

March 22, 2026 · 3 min · santu

为什么Kafka没办法100%保证消息不丢失?

典型回答 Kafka提供的Producer和Consumer之间的消息传递保证语义有三种,所谓消息传递语义,其实就是Kafka的消息交付可靠保障,主要有以下三种: At most once—消息可能会丢,但绝不会重复传递; At least once—消息绝不会丢,但可能会重复传递; Exactly once—每条消息只会被精确地传递一次:既不会多,也不会少; 目前,Kafka 默认提供的交付可靠性保障是第二种,即At least once ,但是,其实依靠Kafka自身,是没有办法100%保证可靠性的。 ✅Kafka如何保证消息不丢失? 上面的文档中,介绍了Kafka在保证消息的可靠性中做的一些努力,但是我们提到,Kafka只对已提交的消息做最大限度的持久化保证不丢失,但是没办法保证100%。 那么,整体分析下为什么吧。 生产者 Kafka允许生产者以异步方式发送消息,这意味着生产者在发送消息后不会等待确认。当然,我们可以注册一个回调等待消息的成功回调。 但是,如果生产者在发送消息之后,Kafka的集群发生故障或崩溃,而消息尚未被完全写入Kafka的日志中,那么这些消息可能会丢失。虽然后续有可能会重试,但是,如果重试也失败了呢?如果这个过程中刚好生产者也崩溃了呢?那就可能会导致没有人知道这个消息失败了,就导致不会重试了。 消费者 消费者来说比较简单,只要保证在消息成功时,才提交偏移量就行了,这样就不会导致消息丢失了。 Broker Kafka使用日志来做消息的持久化的,日志文件是存储在磁盘之上的,但是如果Broker在消息尚未完全写入日志之前崩溃,那么这些消息可能会丢失了。 而且,操作系统在写磁盘之前,会先把数据写入Page Cache中,然后再由操作系统中自己决定什么时候同步到磁盘当中,而在这个过程中,如果还没来得及同步到磁盘中,就直接宕机了,那这个消息也就丢了。 当然,也可以通过配置<font style="color:rgb(18, 18, 18);">log.flush.interval.messages=1</font>,来实现类似于同步刷盘的功能,但是又回到了前面说的情况,还没来得及做持久化,就宕机了。 即使Kafka中引入了副本机制来提升消息的可靠性,但是如果发生同步延迟,还没来及的同步,主副本就挂掉了,那么消息就可能会发生丢失。 这几种情况,只从Broker的角度分析,Broker自身是没办法保证消息不丢失的,但是如果配合Producer,再配合request.required.acks = -1 这种ACK策略,可以确保消息持久化成功之后,才会ACK给Producer,那么, 如果我们的Producer在一定时间段内,没有收到ACK,是可以重新发送的。 但是,这种重新发送,就又回到了我们前面介绍生产者的时候的问题,生产者也有可能挂,重新发送也有可能会没有发送依据,导致消息最终丢失。 所以,我们说,只靠Kafka自己,其实是没有办法保证极端情况下的消息100%不丢失的。 但是,我们也可以在做一些机制来保证,比如引入分布式事务,或者引入本地消息表等,保证在Kafka Broker没有保存消息成功时,可以重新投递消息。这样才行。 ✅常见的分布式事务有哪些?

March 22, 2026 · 1 min · santu

Kafka 为什么有 Topic 还要用 Partition_

典型回答 Topic和Partition是kafka中比较重要的概念。 主题:Topic是Kafka中承载消息的逻辑容器。可以理解为一个消息队列。生产者将消息发送到特定的Topic,消费者从Topic中读取消息。Topic可以被认为是逻辑上的消息流。在实际使用中多用来区分具体的业务。 分区:Partition。是Topic的物理分区。一个Topic可以被分成多个Partition,每个Partition是一个有序且持久化存储的日志文件。每个Partition都存储了一部分消息,并且有一个唯一的标识符(称为Partition ID)。 看上去,这两个都是存储消息的载体,那为啥要分两层呢,有了Topic还需要Partition干什么呢? 在软件领域中,任何问题都可以加一个中间层来解决,而这,就是类似的思想,在Topic的基础上,再细粒度的划分出了一层,主要能带来以下几个好处: 提升吞吐量:通过将一个Topic分成多个Partition,可以实现消息的并行处理。每个Partition可以由不同的消费者组进行独立消费,这样就可以提高整个系统的吞吐量。 负载均衡:Partition的数量通常比消费者组的数量多,这样可以使每个消费者组中的消费者均匀地消费消息。当有新的消费者加入或离开消费者组时,可以通过重新分配Partition的方式进行负载均衡。 扩展性:通过增加Partition的数量,可以实现Kafka集群的扩展性。更多的Partition可以提供更高的并发处理能力和更大的存储容量。 综上,Topic是逻辑上的消息分类,而Partition是物理上的消息分区。通过将Topic分成多个Partition,可以实现提升吞吐量、负载均衡、以及增加可扩展性。

March 22, 2026 · 1 min · santu

Kafka 中的Offset是什么?

典型回答 在 Kafka 中, 每个分区中的每条消息都有一个唯一的编号,称为该消息的“偏移量”(Offset)。偏移量是从 0 开始的整数,表示该分区中消息的顺序。例如,分区中的第一条消息的位移为 0,第二条为 1,依此类推。 Offset也是 Kafka 消费者在某个分区中消费消息的位置标识,即通过位移就知道自己消费到哪了(这里记录的是 Consumer 要消费的下一条消息的位移!!!)。 假设一个parition中有 10 条消息,从 0 到 9。 假设Consumer 已消费了6条消息,这就说明该 Consumer 消费了位移为 0 到 5 的消息,此时 Consumer 的位移应该是 6,而不是5。 Kafka的consumer还会通知kafka自己的消费进度,避免万一消费过程中挂了,下次不知道该从哪开始消费了。所以有两种方式来管理消费位移: 自动提交:消费者会定期自动提交它们的消费位移。这样 Kafka 知道每个消费者上次消费到哪里。 手动提交:消费者可以选择在特定时刻(例如,成功处理完消息后)手动提交位移,确保只有在消息成功处理后才更新位移。 位移、偏移量、都是offset,没有什么固定的叫法和翻译,只不过我认为在队列中叫偏移量,在消费者中叫位移更合适。 假设有一个 Kafka 主题 my_topic,它有 3 个分区,每个分区中有 5 条消息。 分区 0:msg_0, msg_1, msg_2, msg_3, msg_4 分区 1:msg_0, msg_1, msg_2, msg_3, msg_4 分区 2:msg_0, msg_1, msg_2, msg_3, msg_4 假设有两个消费者 C1 和 C2,它们组成一个消费者组。C1 负责消费分区 0 和分区 1,C2 负责消费分区 2。 ...

March 22, 2026 · 1 min · santu

介绍一下Kafka的ISR机制?

典型回答 ISR,是In-Sync Replicas,同步副本的意思。 在Kafka中,每个主题分区可以有多个副本(replica)。。ISR是与主副本(Leader Replica)保持同步的副本集合。ISR机制就是用于确保数据的可靠性和一致性的。 当消息被写入Kafka的分区时,它首先会被写入Leader,然后Leader将消息复制给ISR中的所有副本。只有当ISR中的所有副本都成功地接收到并确认了消息后,主副本才会认为消息已成功提交。这种机制确保了数据的可靠性和一致性。 扩展知识 ISR列表维护 在Kafka中,ISR(In-Sync Replicas)列表的维护是通过副本状态和配置参数来进行的。具体的ISR列表维护机制在不同的Kafka版本中有所变化。 before 0.9.x 在0.9.x之前的版本,Kafka 有一个核心的参数:replica.lag.max.messages,表示如果Follower落后Leader的消息数量超过了这个参数值,就认为Follower就会从ISR列表里移除。 但是,基于replica.lag.max.messages这种实现,在瞬间高并发访问的情况下会有问题:比如Leader瞬间接收到几万条消息,然后所有Follower还没来得及同步过去,此时所有follower都会被踢出ISR列表。 after 0.9.x Kafka从0.9.x版本开始,引入了replica.lag.max.ms参数,表示如果某个Follower的LEO(latest end offset)一直落后Leader超过了10秒,那么才会被从ISR列表里移除。 这样的话,即使出现瞬间流量,导致Follower落后很多数据,但是只要在限定的时间内尽快追上来就行了。

March 22, 2026 · 1 min · santu

Kafka的消费者数量和分区数量可以不同吗?会发生什么?

典型回答 首先,肯定是可以不一样的。如果不一样就两种情况,分区数大于消费者数,或者消费者数大于分区数。 消费者数 ≤ 分区数(推荐做法) 每个消费者至少会分配到一个分区,但不会有消费者闲置。 如果消费者数量 小于 分区数量,一些消费者会消费多个分区的数据,提升吞吐,但可能会导致某些消费者的负载更重。 消费者数 > 分区数(会导致消费者闲置) Kafka 默认不支持多个消费者同时消费同一个分区(除非使用 Kafka 4.0 的共享组)。 由于一个分区只能被一个消费者消费,多出来的消费者无法分配到任何分区,它们会闲置,处于空转状态。 Kafka 4.0 之后的新变化:共享组 在 Kafka 4.0 (2025-03-19发布)引入了共享组(Shared Group),允许多个消费者消费同一个分区,并且支持逐条确认消息。这意味着: 可以用更多的消费者来加速消费速度,即使分区数不变。 多个消费者能并行消费同一个分区,吞吐更高,消费更灵活。

March 22, 2026 · 1 min · santu

留言给博主