目录
- kafka是什么
- kafka核心组件
- kafka应用场景
- kafka解决的难题
- kafka的底层原理
- kafka的消费者是pull还是push模式,这种模式的好处?
- Zookeeper对于Kafka的作用
- Kafka维护消息状态的跟踪方法
- Kafka判断节点活着的两个条件
- Kafka中ack的三种机制
- kafka是怎么保证消息不被重复消费的
- 分布式情况下,如何保证消息的顺序消费
- kafka如何不消费重复数据
- 讲一下kafka集群的组成
- partition的数据文件(offffset,MessageSize,data)
- kafka如何实现数据的高效读取?(顺序读写、分段命令、二分查找)
- [Kafka 消费者端的Rebalance 操作什么时候发生](#Kafka 消费者端的Rebalance 操作什么时候发生)
- Kafka中的ISR(InSyncRepli)、OSR(OutSyncRepli)、AR(AllRepli)代表什么
- Kafka中的HW、LEO等分别代表什么
- Kafka的那些设计让它有如此高的性能?
- Kafka为什么不支持读写分离
- 分区Leader选举策略有几种
- 请谈一谈Kafka数据一致性原理
- Kafka缺点
- kafka保证消息被顺利消费
- 知识点
- 字节跳动
kafka是什么
Kafka 是一个开源的分布式流处理平台,由 Apache 软件基金会开发和维护。它主要用于构建实时数据流处理应用程序,以满足高吞吐量、低延迟和高可扩展性的需求。Kafka 可以处理数百亿次的事件(如消息、日志、指标等)并将其传输到多个订阅者。特点是高吞吐量、持久性、分布式
kafka核心组件
-
Producer:生产者是负责将数据(如消息、日志、指标等)发送到 Kafka 集群的客户端应用。生产者将数据发送到一个或多个 Kafka 主题(Topic)
-
Topic:主题是 Kafka 中数据的逻辑分类。数据的生产者将消息发送到特定的主题,而消费者订阅这些主题以接收数据
-
Partition:分区是 Kafka 主题的物理组织方式。一个主题可以拆分为多个分区,每个分区可以独立存储和处理数据。分区允许 Kafka 在多个服务器上并行处理数据,从而实现高可扩展性
-
Broker:代理是 Kafka 集群中的单个服务器。一个 Kafka 集群可以包含多个代理,这些代理共同协作以存储和处理数据。代理负责接收生产者发送的数据和向消费者提供数据
-
Consumer:消费者是从 Kafka 集群订阅和处理数据的客户端应用。消费者可以订阅一个或多个主题,并从中获取数据进行处理
-
Zookeeper:需要zk来做分布式协调
kafka应用场景
Kafka 是一个高性能、可扩展的分布式流处理平台,它在许多不同的应用场景中都有广泛的用途。以下是一些 Kafka 的典型用途:
- 日志聚合:Kafka 可以用于收集和传输大量的日志数据,以便集中存储和处理。这有助于实现对日志数据的实时监控、分析和报告。
- 数据流处理:Kafka 可以用于构建实时数据流处理管道,以便对数据进行过滤、转换、聚合和分析等操作。这对于实时数据监控、实时报表生成和实时推荐等应用场景非常有用。
- 消息队列:Kafka 可以作为一个高性能、可扩展的消息队列系统,用于在分布式系统中传输数据。这有助于实现系统的解耦,从而提高系统的可维护性和可扩展性。
- 事件驱动架构:Kafka 可以用于构建事件驱动的微服务架构,以提高系统的解耦和可扩展性。在这种架构中,各个微服务之间通过 Kafka 传递事件,从而实现异步通信和松耦合。
- 数据同步:Kafka 可以用于实现跨系统、跨数据库的数据同步。通过将数据变更作为事件发送到 Kafka,其他系统和数据库可以订阅这些事件,并根据需要实时更新自己的数据。
- 大数据处理:Kafka 可以作为大数据处理平台(如 Hadoop、Spark 等)的数据源,提供实时或批量的数据输入。这有助于实现对大规模数据的实时或离线分析、挖掘和机器学习。
- 实时监控和报警:Kafka 可以用于实时监控系统状态、性能指标和业务指标。通过实时分析 Kafka 中的数据,可以实现对异常情况的实时检测和报警。
- 分布式事务:Kafka 可以用于支持分布式事务,在多个服务或组件之间进行协调和状态同步。通过 Kafka 传递事务状态和命令,可以实现对分布式事务的管理和控制。
这些仅仅是 Kafka 的部分用途,实际上 Kafka 在不同行业和场景下还有更多的应用。总之,Kafka 作为一个高性能、可扩展的分布式流处理平台,具有广泛的应用价值。
kafka解决的难题
Kafka 的设计初衷是为了解决大规模分布式系统中的数据流处理问题。它主要解决以下几个方面的问题:
-
高吞吐量和低延迟数据传输:Kafka 能够在分布式环境中高效地处理大量的数据流,以满足实时数据处理和传输的需求。
-
可扩展性:Kafka 具有良好的可扩展性,可以通过添加更多的代理(Broker)节点来扩展集群,以支持更高的吞吐量和更大的数据量。这对于大型分布式系统和云计算环境非常重要。
-
数据持久性:Kafka 可以将数据持久化到磁盘,保证数据不会丢失。这对于关键业务数据和日志数据的处理非常重要。
-
分布式和高可用:Kafka 是一个分布式系统,它可以在多个节点上运行以实现负载均衡和容错。当某个节点发生故障时,Kafka 集群仍然可以继续提供服务。
-
消息订阅和消费:Kafka 提供了灵活的消息订阅和消费机制,允许多个消费者订阅同一个主题(Topic)并并行处理数据。这有助于实现数据的实时处理和分析。
-
解耦生产者和消费者:Kafka 可以作为一个中间数据存储层,解耦数据的生产者和消费者。这有助于提高系统的可维护性和可扩展性,同时减轻对单个组件的性能压力。
-
数据同步和集成:Kafka 可以作为一个集成平台,用于实现不同系统和数据库之间的数据同步。这有助于构建统一的数据处理和分析平台,降低数据孤岛的影响。
-
跨平台和多语言支持:Kafka 提供了多种编程语言的客户端库,以支持不同平台和语言的应用程序。这有助于实现跨平台和跨语言的数据交互和集成。
总之,Kafka 主要解决了分布式系统中的数据流处理、传输、存储和集成等问题,为构建高性能、实时和可扩展的数据处理系统提供了基础设施。
kafka的底层原理
Kafka 的底层原理主要包括以下几个方面:
数据模型
Kafka 使用发布-订阅模型,数据以消息(Message)的形式被生产者(Producer)发布到主题(Topic)中。消费者(Consumer)可以订阅一个或多个主题以接收和处理消息。主题被划分为多个分区(Partition),每个分区中的消息按照先进先出(FIFO)的顺序存储并具有唯一的偏移量(Offset)。
数据持久化
Kafka 将消息持久化到磁盘,以保证数据不会丢失。每个分区的数据被存储为一个单独的日志文件,文件按照大小或时间进行滚动。Kafka 使用顺序写入的方式来优化磁盘 I/O 性能。
分布式和副本
Kafka 是一个分布式系统,由多个代理(Broker)组成。每个分区可以有多个副本(Replica),分布在不同的代理上。其中一个副本被选为领导者(Leader)负责处理消息的读写,其他副本作为追随者(Follower)同步领导者的数据。当领导者发生故障时,会自动选举一个新的领导者。
生产者
生产者负责将消息发布到 Kafka 主题。生产者会将消息发送到主题的一个分区,分区的选择可以基于消息的 key 进行哈希分配,也可以使用自定义的分区策略。生产者可以配置消息的确认级别(acks)以控制消息的可靠性和性能。
消费者和消费者组
消费者负责从 Kafka 主题中读取和处理消息。消费者可以组成消费者组(Consumer Group),组内的消费者协同处理同一个主题的消息,以实现负载均衡和并行处理。消费者使用偏移量(Offset)来记录每个分区已消费的消息位置,偏移量可以存储在 Kafka 或外部系统中。
数据同步
Kafka 使用复制协议(Replication Protocol)来同步分区的副本数据。领导者将收到的消息写入本地日志后,会将消息发送给追随者。追随者接收到消息后,也将消息写入本地日志并发送 ACK 给领导者。领导者收到所有追随者的 ACK 后,认为消息已经被复制成功。
容错和高可用
Kafka 通过领导者选举(Leader Election)机制来实现容错和高可用。当一个分区的领导者发生故障时,Kafka 会自动从追随者中选举一个新的领导者。选举过程中,该分区的读写请求会暂时被阻塞,但其他分区仍然可以正常处理请求。
应用接口
Kafka 提供了生产者和消费者的客户端库,支持多种编程语言。用户可以通过这些客户端库来实现消息的发布和订阅,与 Kafka 集群进行交互。
通过这些底层原理,Kafka 实现了高性能、分布式、持久化、可扩展和高可用的数据流处理平台。
kafka的消费者是pull还是push模式,这种模式的好处?
Kafka 的消费者使用 pull(拉)模式来获取数据。这意味着消费者主动从 Kafka broker 请求数据,而不是等待 broker 将数据推送到消费者。这种 pull 模式的好处有:
-
流控制:消费者可以根据自己的处理能力来控制拉取数据的速率,避免因为处理速度跟不上消息推送速度而导致的积压问题。这有助于维护消费者的稳定性和可靠性。
-
可扩展性:在 pull 模式下,可以轻松地添加或减少消费者数量,以应对不同的负载需求。当需要更多消费者处理消息时,可以简单地将它们加入消费者组,从而实现水平扩展。
-
高性能:在 pull 模式下,消费者可以批量拉取消息,从而提高处理效率。这有助于提高整体系统的吞吐量和性能。
-
容错性:Kafka 通过分区(Partition)和副本(Replica)来实现高可用和数据冗余。在 pull 模式下,如果某个消费者故障,其他消费者可以继续从故障消费者的当前位置开始拉取消息,从而确保消息的连续性。
-
简化设计:在 pull 模式下,消费者不需要维护一个长连接,而是通过轮询的方式获取数据。这可以简化消费者的设计,减少连接管理的复杂性。
总之,Kafka 中使用 pull 模式的消费者可以提供更好的可扩展性、性能和容错性,有助于构建高效、可靠的分布式消息系统。
Zookeeper对于Kafka的作用
ZooKeeper 是一个分布式的、开源的协调服务,用于管理分布式应用中的配置信息、命名空间、同步等。在 Kafka 中,ZooKeeper 主要承担以下职责:
-
集群元数据管理:ZooKeeper 存储了 Kafka 集群的元数据信息,包括 broker 列表、主题和分区信息等。当新的 broker 加入或者现有 broker 离开集群时,ZooKeeper 能够感知到这些变化,并通知其他 broker 更新元数据。
-
控制器选举:Kafka 集群中有一个特殊的 broker 角色叫控制器(Controller),负责管理分区的副本分配、故障恢复等。ZooKeeper 负责在集群中选举一个控制器,确保集群中只有一个控制器。当当前控制器出现故障时,ZooKeeper 会选举一个新的控制器来替代。
-
分区领导者选举:Kafka 中的每个分区都有一个领导者(Leader)副本和若干个追随者(Follower)副本。领导者负责处理客户端的读写请求,追随者负责从领导者同步数据。ZooKeeper 负责在分区的副本中选举一个领导者,并在领导者故障时选举新的领导者。
-
消费者组管理:Kafka 支持消费者组,消费者组内的消费者可以并行消费同一个主题的不同分区。ZooKeeper 用于存储消费者组的信息,包括消费者列表、消费者位置(偏移量)等。当消费者组内的消费者发生变化时,ZooKeeper 能够感知到这些变化,并触发再平衡操作。
总之,ZooKeeper 在 Kafka 中主要用于管理集群元数据、协调分布式操作和维护消费者组信息。通过使用 ZooKeeper,Kafka 可以实现高可用、可靠和可扩展的分布式消息系统。
Kafka维护消息状态的跟踪方法
Kafka 使用消费者偏移量(Consumer Offset)来跟踪每个消费者组对每个分区中消息的消费状态。消费者偏移量是一个递增的整数,表示消费者已经消费到分区中的哪个位置。这里是 Kafka 维护消息状态的跟踪方法:
-
消费者偏移量:当消费者开始消费一个分区的消息时,它会从某个偏移量开始。该偏移量可以是最早的消息偏移量(从头开始消费),也可以是最新的消息偏移量(从最新的消息开始消费),或者是上次消费的偏移量(从上次停止的地方继续消费)。
-
更新消费者偏移量:当消费者从分区读取并处理一条消息后,它需要将消费者偏移量加 1,表示已经处理了当前消息。消费者可以选择在每次消费消息后更新偏移量,也可以选择批量消费一组消息后更新偏移量。批量更新偏移量可以提高性能,但是可能导致在故障恢复时重新处理部分消息。消费者应根据业务需求和容忍度来选择合适的更新策略。
-
提交消费者偏移量:为了在消费者故障时能够从上次消费的位置继续消费,消费者需要将消费者偏移量定期提交(Commit)到 Kafka 或者 ZooKeeper。提交消费者偏移量可以是同步的(同步提交后才继续消费消息)或异步的(在提交偏移量的同时继续消费消息)。
-
再平衡和故障恢复:当消费者组内的消费者发生变化(如新增消费者、消费者故障等)时,Kafka 会触发再平衡操作,重新分配分区给消费者。在这个过程中,新的消费者会根据已提交的消费者偏移量来开始消费分区中的消息。这可以确保消息在故障恢复后能够连续地被消费。
通过这种方法,Kafka 可以准确地跟踪消费者组对每个分区中消息的消费状态,并在故障恢复时保证消息的连续性。这种方法还允许消费者根据自己的处理能力来控制消费速度,实现高效、可靠的消息消费。
Kafka判断节点活着的两个条件
- 节点必须维护和 ZooKeeper 的连接,Zookeeper 通过心跳机制检查每个节点的连接
- 如果节点是个 follower,他必须能及时的同步 leader 的写操作,延时不能太久
Kafka中ack的三种机制
Kafka 提供了三种不同的消息确认(acknowledgment)机制,它们分别对应于不同的数据可靠性和性能要求。acks
是一个生产者配置参数,用于设置消息确认机制。以下是 Kafka 中 ack 的三种机制:
-
acks=0 (无确认):在这种模式下,生产者发送消息后不会等待任何确认,即使消息没有被成功写入 Kafka。这种模式提供了最高的吞吐量,但是数据安全性较低,因为在 broker 故障时可能会丢失消息。
-
acks=1 (只确认领导者):在这种模式下,生产者发送消息后只需等待分区领导者(Leader)确认收到消息。一旦领导者确认收到消息,生产者就认为消息已经成功写入。这种模式提供了较好的吞吐量和数据安全性,但是在领导者故障时仍然可能会丢失消息。
-
acks=all 或 acks=-1 (确认所有副本):在这种模式下,生产者发送消息后需要等待分区领导者和所有追随者(Follower)副本都确认收到消息。这种模式提供了最高的数据安全性,因为只有当所有副本都确认收到消息后,生产者才认为消息已经成功写入。然而,这种模式的吞吐量较低,因为需要等待所有副本的确认。
选择合适的 ack 机制需要根据应用的可靠性和性能要求进行权衡。如果对数据安全性要求较高,可以选择 acks=all;如果对吞吐量要求较高,可以选择 acks=1 或 acks=0。在实际应用中,acks=1 是一种常用的折衷方案,它提供了较好的吞吐量和数据安全性。
kafka是怎么保证消息不被重复消费的
Kafka使用一种称为"偏移量(offset)"的机制来保证消息不被重复消费。偏移量是一个标识符,用于唯一标识每条消息在分区内的位置。当消费者读取消息时,它会跟踪已消费的最后一个偏移量,并将其提交给Kafka,表示已经成功处理了该偏移量之前的所有消息。
Kafka采用"至少一次"语义,这意味着当消费者处理消息时,可能会发生一次或多次重复消费的情况。为了应对这种情况,Kafka允许消费者控制偏移量的提交时机。一般情况下,消费者在处理完消息后会立即提交偏移量,以确保消息被准确地处理。
此外,Kafka还提供了可重置偏移量的功能。消费者可以将偏移量重置到较早的位置,从而重新消费一些消息。这在某些场景下非常有用,比如消费者出现错误或需要重新处理数据。
总结起来,Kafka通过偏移量机制和消费者控制偏移量提交的时机,以及提供偏移量重置的功能,来保证消息不被重复消费。
分布式情况下,如何保证消息的顺序消费
Kafka 中发送 1 条消息的时候,可以指定(topic, partition, key) 3 个参数,partiton 和 key 是可选的。
Kafka 分布式的单位是 partition,同一个 partition 用一个 write ahead log 组织,所以可以保证FIFO 的顺序。不同 partition 之间不能保证顺序。因此你可以指定 partition,将相应的消息发往同 1个 partition,并且在消费端,Kafka 保证1 个 partition 只能被1 个 consumer 消费,就可以实现这些消息的顺序消费。
另外,你也可以指定 key(比如 order id),具有同 1 个 key 的所有消息,会发往同 1 个partition,那这样也实现了消息的顺序消息。
kafka如何不消费重复数据
这个问题换种问法,就是kafka如何保证消息的幂等性。对于消息队列来说,出现重复消息的概率还是挺大的,不能完全依赖消息队列,而是应该在业务层进行数据的一致性幂等校验。
比如你处理的数据要写库(mysql,redis等),你先根据主键查一下,如果这数据都有了,你就别插入了,进行一些消息登记或者update等其他操作。另外,数据库层面也可以设置唯一健,确保数据不要重复插入等 。一般这里要求生产者在发送消息的时候,携带全局的唯一id。
讲一下kafka集群的组成
Broker(代理)
Kafka集群通常由多个代理组成以保持负载平衡。 Kafka代理是无状态的,所以他们使用ZooKeeper来维护它们的集群状态。 一个Kafka代理实例可以每秒处理数十万次读取和写入,每个Broker可以处理TB的消息,而没有性能影响。 Kafka经纪人领导选举可以由ZooKeeper完成。
ZooKeeper
ZooKeeper用于管理和协调Kafka代理。 ZooKeeper服务主要用于通知生产者和消费者Kafka系统中存在任何新代理或Kafka系统中代理失败。 根据Zookeeper接收到关于代理的存在或失败的通知,然后生产者和消费者采取决定并开始与某些其他代理协调他们的任务。
Producers(生产者)
生产者将数据推送给经纪人。 当新代理启动时,所有生产者搜索它并自动向该新代理发送消息。 Kafka生产者不等待来自代理的确认,并且发送消息的速度与代理可以处理的一样快。
Consumers(消费者)
因为Kafka代理是无状态的,这意味着消费者必须通过使用分区偏移来维护已经消耗了多少消息。 如果消费者确认特定的消息偏移,则意味着消费者已经消费了所有先前的消息。 消费者向代理发出异步拉取请求,以具有准备好消耗的字节缓冲区。 消费者可以简单地通过提供偏移值来快退或跳到分区中的任何点。 消费者偏移值由ZooKeeper通知。
partition的数据文件(offffset,MessageSize,data)
partition中的每条Message包含了以下三个属性: offset,MessageSize,data,其中offset表示Message在这个partition中的偏移量,offset不是该Message在partition数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了partition中的一条Message,可以认为offset是partition中Message的 id; MessageSize表示消息内容data的大小;data为Message的具体内容。
kafka如何实现数据的高效读取?(顺序读写、分段命令、二分查找)
Kafka为每个分段后的数据文件建立了索引文件,文件名与数据文件的名字是一样的,只是文件扩展名为index。 index文件中并没有为数据文件中的每条Message建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。
Kafka 消费者端的Rebalance 操作什么时候发生
-
同一个 consumer 消费者组 group.id 中,新增了消费者进来,会执行 Rebalance 操作
-
消费者离开当期所属的 consumer group组。比如宕机
-
分区数量发生变化时(即 topic 的分区数量发生变化时)
-
消费者主动取消订阅
Rebalance的过程如下:
第一步:所有成员都向coordinator发送请求,请求入组。一旦所有成员都发送了请求,coordinator会从中选择一个consumer担任leader的角色,并把组成员信息以及订阅信息发给leader。
第二步:leader开始分配消费方案,指明具体哪个consumer负责消费哪些topic的哪些partition。一旦完成分配,leader会将这个方案发给coordinator。coordinator接收到分配方案之后会把方案发给各个consumer,这样组内的所有成员就都知道自己应该消费哪些分区了。
所以对于Rebalance来说,Coordinator起着至关重要的作用
Kafka中的ISR(InSyncRepli)、OSR(OutSyncRepli)、AR(AllRepli)代表什么
答:kafka中与leader副本保持一定同步程度的副本(包括leader)组成ISR。与leader滞后太多的副本组成OSR。分区中所有的副本通称为AR。
ISR : 速率和leader相差低于10秒的follower的集合
OSR : 速率和leader相差大于10秒的follower
AR : 全部分区的follower
Kafka中的HW、LEO等分别代表什么
答:HW:高水位,指消费者只能拉取到这个offset之前的数据
LEO:标识当前日志文件中下一条待写入的消息的offset,大小等于当前日志文件最后一条消息的offset+1.
Kafka的那些设计让它有如此高的性能?
- kafka是分布式的消息队列
- 对log文件进行了segment,并对segment创建了索引
- (对于单节点)使用了顺序读写,速度能够达到600M/s
- 引用了zero拷贝,在os系统就完成了读写操做
Kafka为什么不支持读写分离
1、 这其实是分布式场景下的通用问题,因为我们知道CAP理论下,我们只能保证C(一致性)和A(可用性)取其一,如果支持读写分离,那其实对于一致性的要求可能就会有一定折扣,因为通常的场景下,副本之间都是通过同步来实现副本数据一致的,那同步过程中肯定会有时间的消耗,如果支持了读写分离,就意味着可能的数据不一致,或数据滞后。
2、 Leader/Follower模型并没有规定Follower副本不可以对外提供读服务。很多框架都是允许这么做的,只是 Kafka最初为了避免不一致性的问题,而采用了让Leader统一提供服务的方式。
3、 不过,自Kafka 2.4之后,Kafka提供了有限度的读写分离,也就是说,Follower副本能够对外提供读服务。
分区Leader选举策略有几种
分区的Leader副本选举对用户是完全透明的,它是由Controller独立完成的。你需要回答的是,在哪些场景下,需要执行分区Leader选举。每一种场景对应于一种选举策略。
1、 OfflinePartition Leader选举:每当有分区上线时,就需要执行Leader选举。所谓的分区上线,可能是创建了新分区,也可能是之前的下线分区重新上线。这是最常见的分区Leader选举场景。
2、 ReassignPartition Leader选举:当你手动运行Kafka-reassign-partitions命令,或者是调用Admin的alterPartitionReassignments方法执行分区副本重分配时,可能触发此类选举。假设原来的AR是[1,2,3],Leader是1,当执行副本重分配后,副本集合AR被设置成[4,5,6],显然,Leader必须要变更,此时会发生Reassign Partition Leader选举。
3、 PreferredReplicaPartition Leader选举:当你手动运行Kafka-preferred-replica-election命令,或自动触发了Preferred Leader选举时,该类策略被激活。所谓的Preferred Leader,指的是AR中的第一个副本。比如AR是[3,2,1],那么,Preferred Leader就是3。
4、 ControlledShutdownPartition Leader选举:当Broker正常关闭时,该Broker上的所有Leader副本都会下线,因此,需要为受影响的分区执行相应的Leader选举。
这4类选举策略的大致思想是类似的,即从AR中挑选首个在ISR中的副本,作为新Leader。
#请简述下你在哪些场景下会选 Kafka
- 日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、HBase、Solr等。
- 消息系统:解耦和生产者和消费者、缓存消息等。
- 用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
- 运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
- 流式处理:比如spark streaming和 Flink
请谈一谈Kafka数据一致性原理
一致性就是说不论是老的 Leader 还是新选举的 Leader,Consumer 都能读到一样的数据。
假设分区的副本为3,其中副本0是 Leader,副本1和副本2是 follower,并且在 ISR 列表里面。虽然副本0已经写入了 Message4,但是 Consumer 只能读取到 Message2。因为所有的 ISR 都同步了 Message2,只有 High Water Mark 以上的消息才支持 Consumer 读取,而 High Water Mark 取决于 ISR 列表里面偏移量最小的分区,对应于上图的副本2,这个很类似于木桶原理。
这样做的原因是还没有被足够多副本复制的消息被认为是"不安全"的,如果 Leader 发生崩溃,另一个副本成为新 Leader,那么这些消息很可能丢失了。如果我们允许消费者读取这些消息,可能就会破坏一致性。试想,一个消费者从当前 Leader(副本0) 读取并处理了 Message4,这个时候 Leader 挂掉了,选举了副本1为新的 Leader,这时候另一个消费者再去从新的 Leader 读取消息,发现这个消息其实并不存在,这就导致了数据不一致性问题。
当然,引入了 High Water Mark 机制,会导致 Broker 间的消息复制因为某些原因变慢,那么消息到达消费者的时间也会随之变长(因为我们会先等待消息复制完毕)。延迟时间可以通过参数 replica.lag.time.max.ms 参数配置,它指定了副本在复制消息时可被允许的最大延迟时间。
Kafka缺点
由于是批量发送,数据并非真正的实时;
•对于mqtt协议不支持;
•不支持物联网传感数据直接接入;
•仅支持统一分区内消息有序,无法实现全局消息有序;
•监控不完善,需要安装插件;
•依赖zookeeper进行元数据管理;
kafka保证消息被顺利消费
Kafka 是一种分布式流处理平台,它使用发布-订阅的消息队列模型来处理消息。Kafka 本身提供了一些机制来确保消息被顺利消费掉,下面是一些常见的方法:
-
消费者偏移量管理:Kafka 使用偏移量(offset)来标识消息在分区中的位置。消费者可以通过跟踪偏移量来确定下一个要消费的消息。消费者可以定期提交偏移量,以便记录其消费进度。这样,在消费者重新启动时,它可以从上次提交的偏移量继续消费消息,确保不会错过任何消息。
-
手动提交偏移量:消费者可以选择手动提交偏移量,而不是自动提交。这样可以确保只有在消息处理成功后才提交偏移量。通过手动提交偏移量,您可以控制消费者的消费速率和处理顺序,确保消息被顺利消费掉。
-
消费者组:Kafka 允许多个消费者组消费同一个主题的消息。每个消费者组内的消费者会共享消息的负载,每个消费者负责处理一部分分区。这样可以提高整体的消费能力和容错能力。当一个消费者组中的消费者失败或离线时,其他消费者可以接管它们负责的分区,确保消息被消费掉。
-
消息回溯和重试:如果消费者由于某种原因处理失败,可以回溯到之前的偏移量,并重新消费消息。Kafka 允许消费者按照指定的偏移量重新消费消息,这对于处理失败的消息或者重放消息非常有用。
-
消息持久化:Kafka 将消息持久化到磁盘上,确保消息在存储层面的可靠性。即使消费者在消息发送后离线,消息仍然可以在 Kafka 中保持,等待消费者重新连接并消费。
知识点
原理
- 消费者组
相同的数据会被不同的消费组消费多次,同一组内一个消费者只能消费一个分区,消费者大于分区数将会被空闲
- 消费者
消费者会记录消费的物理偏移量,一个分片对应一个消费者成员,如果消费者组中成员太多会有空闲成员
- 顺序
kafka每个partition中的消息在写入时都是有序的,消费时,每个partition只能被一个group中的一个消费者消费,保证了消费时也是顺序的,整个topic不保证有序,如果保证topic整个有序,那么将partition调整为1
- Rebalance
Rebalance本质上是一种协议,规定了一个消费者组下所有消费者如何达成一致,来分配订阅topic的每个分区,Rebalance重平衡,发生时机如下:
1.组成员数量发生变化;2. 订阅主题数量发生变化 ; 3. 订阅主题的分区发生变化
- 消息存储结构
kafka每个partition对应唯一一个文件夹,消息采用Segment File的存储方式;Segment File的意思是:将大文件拆分成小文件存储,这样大文件就变成一段一段(Segment段),这样的好处是IO加载速度快;稀疏索引:并不为每条数据建立索引,而是隔几条建立一个索引,找到位置再遍历(需要有序),减少了内存消耗
正常使用场景
- 削峰
性能好,如下:
-
分布式:kafka是一个分布式系统,由多个broker组成,每个topic可以划分为多个partition,这些partition可以分布在不同broker上,提高了系统的处理能力;分区:通过多个partition,topic上的数据被分散到多个broker,kafka可以在多个broker上并行处理,kafka中的消费者使用偏移量来跟踪每个分区的读取进度;复制:通过存储topic的多个副本,以保证数据的持久性和可靠性
-
持久化:kafka内部是顺序IO加缓存提高消息存储速度,不用处理业务,能很快让接口返回
-
零拷贝:数据传输过程中使用零拷贝技术(sendfile和mmap),减少数据在内核空间与用户空间之间的拷贝;两种方式:
-
网络数据持久化到磁盘 (Producer 到 Broker) 使用mmap
-
- mmap将磁盘文件映射到内存, 用户通过修改内存就能修改磁盘文件
- 写到mmap中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘(不可靠)
- Kafka提供了一个参数producer.type来控制是不是主动flush(不可靠)
- 如果Kafka写入到mmap之后就立即flush然后再返回Producer叫同步(sync);写入mmap之后立即返回Producer不调用flush叫异步(async)(不可靠)
-
磁盘文件通过网络发送(Broker 到 Consumer)使用sendfile
-
- sendfile系统调用可以将数据从文件描述符发送到另一个文件描述符,这个过程始终在内核空间,因此可以实现零拷贝
- kafka发送数据时,使用sendfile系统调用将数据直接从磁盘发送到网络Socket
-
-
批处理:支持将消息打包再一起发送,减少网络请求次数,提高处理效率
-
消息压缩:支持消息压缩,有效减少网络传输和磁盘存储的开销
- 解耦
- 服务间解耦用消息队列
- 服务内解耦用事件总线
消息丢失场景
- 生产者丢失场景
- broker消息丢失:kafka为了得到更高的性能和吞吐量,将数据异步批量的存储在磁盘中
- 消费者消息丢失:手动提交offset
如何保证消息不丢
- 副本
topic创建时,可以设定这个这题要创建多个副本,每个副本在不同的broker上
- ack机制
- 0:kafka不会等待broker的ack,延迟低,但当server挂掉可能会丢失数据
- 1:等待leader确认收到发送的ack消息,如果此时leader挂掉,不保证新leader上存在次数据
- -1:等待所有follower收到数据才发送ack
- 重试
kafka生产者配置中,有一个retries参数,用于设置生产者发送消息失败后的重试次数
参考资料
字节跳动
kafka消息推送订阅怎么实现的
Kafka 是一个分布式的消息队列系统,用于支持高吞吐量的消息发布和订阅模式。在 Kafka 中,消息的发布和订阅是通过以下方式实现的:
- 创建主题(Topic):在 Kafka 中,消息按照主题进行分类和组织。首先,需要创建一个或多个主题来存储消息。主题可以根据业务需求进行划分,例如按照功能、数据类型或者其他维度进行划分。
- 发布消息(Producer):消息的发布方(Producer)将消息发送到 Kafka 集群中的指定主题。Producer 可以使用 Kafka 提供的客户端库来与 Kafka 集群进行交互,通过调用相应的 API 将消息发送到指定的主题。
- 订阅消息(Consumer):消息的订阅方(Consumer)可以订阅一个或多个主题,以接收发送到这些主题的消息。Consumer 也使用 Kafka 提供的客户端库来与 Kafka 集群进行交互。订阅方可以使用订阅 API 来注册对特定主题的订阅,并从所订阅的主题中接收消息。
- 消息分区和消费组:Kafka 中的主题可以被划分为多个分区(Partition),每个分区可以在不同的节点上进行复制和存储。每个分区中的消息按照顺序进行存储,并使用唯一的偏移量(Offset)进行标识。消费者可以以消费组(Consumer Group)的形式组织,每个消费组中的消费者共同消费一个或多个主题的消息。Kafka 会将消息均匀地分配给消费者组中的消费者,以实现消息的负载均衡和高可用性。
- 消费者拉取和提交偏移量:消费者通过拉取(Pull)的方式从 Kafka 中获取消息。消费者可以定期从分区中拉取一批消息,并进行处理。消费者使用偏移量来跟踪已经消费过的消息的位置。一旦消费者成功处理了一批消息,它可以提交偏移量,表示已经消费完成,以便下次拉取时从正确的位置开始。
通过以上的机制,Kafka 实现了高吞吐量的消息发布和订阅模式。生产者将消息发送到指定主题,消费者订阅感兴趣的主题并拉取消息进行处理。Kafka 的分布式架构和分区机制保证了消息的可靠性和可扩展性。
broker是什么
在消息队列系统中,Broker(代理服务器)是指中间件或服务器,负责接收、存储和转发消息。它是消息队列系统的核心组件,用于协调消息的发布和订阅过程。
具体来说,在消息队列系统中,生产者(Producer)将消息发送给 Broker,而消费者(Consumer)从 Broker 接收消息。Broker 负责管理消息的存储和传递,并提供一些额外的功能,如消息持久化、消息路由、消息过滤、消息排序等。
Broker 扮演了一个中间角色,它接收来自生产者的消息,并将其存储在一个或多个队列中。这些队列可以根据主题或其他规则进行划分。消费者可以订阅感兴趣的主题或队列,并从 Broker 中拉取或接收消息。
Broker 还负责处理消费者的订阅和取消订阅请求,以及管理消费者组(Consumer Group)和分区(Partition)等概念。
kafka是怎么存储数据的
Kafka使用一种基于日志的存储模型来持久化消息数据。在Kafka中,每个主题(Topic)被划分为一个或多个分区(Partition),每个分区是一个有序、不可变的消息日志。每个分区中的消息按照写入的顺序进行追加,并根据唯一的偏移量(Offset)进行标识。
消息在Kafka中的存储过程如下:
- 分区(Partition):每个主题可以划分为多个分区,每个分区是一个有序的消息日志。
- 消息追加:生产者(Producer)将消息发送到特定主题的分区。Kafka将这些消息追加到分区的日志末尾,形成一个有序的消息序列。
- 分段(Segment):为了提高读写性能和管理存储空间,Kafka将每个分区的日志分为多个分段,每个分段都是一个独立的文件。每个分段有一个固定的大小限制(通过配置参数设置),当分段的大小达到限制时,将创建一个新的分段。
- 索引(Index):为了快速定位消息的位置,Kafka在内存中维护了一个索引结构。该索引基于偏移量和消息的物理位置,使得可以根据偏移量快速查找消息所在的分段和位置。
- 数据保留策略:Kafka支持根据时间或存储大小来设置数据保留策略。根据策略,旧的分段将被删除或压缩,以释放存储空间。
通过这种设计,Kafka实现了高性能和持久化存储。消息的顺序追加和基于索引的读取使得Kafka能够高效地处理大量的消息,并提供高吞吐量和低延迟的消息传递能力。同时,分区和分段机制使得Kafka可以水平扩展,处理更大规模的数据和负载。
偏移量(Offset)进行标识什么
在Kafka中,偏移量(Offset)是用来唯一标识每个消息在分区中的位置的值。它表示消息在特定分区中的相对位置,用于确定消费者(Consumer)在消费消息时的起始点和进度。
具体来说,偏移量是一个64位的整数值,每个分区中的消息都有一个唯一的偏移量与之对应。Kafka通过递增的方式为每条消息分配偏移量,新写入的消息的偏移量总是比之前写入的消息的偏移量更大。
偏移量的作用如下:
- 消费者位置:偏移量用于标识消费者在分区中消费消息的位置。消费者可以跟踪自己已经消费过的消息的偏移量,以便在断开连接或重新启动后,从上次消费的位置继续消费。
- 消费者组协调:偏移量还用于协调消费者组(Consumer Group)中各个消费者之间的工作负载分配。Kafka会记录每个消费者组在每个分区上消费的偏移量,以确保每个消费者在分区上消费的消息都是连续的。消费者组协调器(Consumer Group Coordinator)会定期提交消费者的偏移量,并处理重新平衡(Rebalance)时的偏移量分配。
- 消息回溯和重放:偏移量允许消费者根据需要回溯和重放消息。消费者可以通过指定特定的偏移量来重新消费过去的消息,或者从最早的偏移量开始消费所有消息。
每个分区都有偏移量,怎么知道从哪读
在 Kafka 中,每个消费者都可以跟踪每个分区的当前消费偏移量。消费者可以通过以下两种方式来确定从哪个偏移量开始读取消息:
- 手动指定偏移量:消费者可以显式地指定从特定的偏移量开始消费消息。这种方式适用于需要按照特定需求进行灵活控制的情况。消费者可以通过设置
Seek()
或assign()
方法来指定偏移量。通过指定具体的偏移量,消费者可以从该偏移量对应的消息开始消费。 - 自动管理偏移量:Kafka 提供了一种自动管理消费偏移量的机制。消费者可以使用
subscribe()
方法订阅一个或多个主题,并加入一个消费者组(Consumer Group)。Kafka 会自动为消费者组中的每个消费者分配分区,并跟踪每个消费者在每个分区中的偏移量。消费者会自动从上次提交的偏移量处开始消费,如果是首次消费或者没有提交过偏移量,则会从最早的可用偏移量开始消费。
在自动管理偏移量的情况下,Kafka 还提供了两种不同的消费模式:最早(earliest)和最新(latest)。
- 最早模式:消费者会从分区的最早可用偏移量开始消费,即最老的未被删除的消息。
- 最新模式:消费者会从分区的最新可用偏移量开始消费,即最新写入的消息。
消费者可以通过在 subscribe()
方法中指定消费模式来选择合适的模式。
总结起来,消费者可以手动指定偏移量,或者使用自动管理偏移量的机制来确定从哪个偏移量开始读取消息。这样可以实现根据需求控制消费位置的灵活性,并确保消费者能够从正确的位置开始消费消息。