当前位置: 首页 > 知识库问答 >
问题:

Kafka Stream中幂等性与精确一次的区别

商天逸
2023-03-14

我正在浏览文档,我知道通过启用幂等性=true

幂等性:幂等生成函数对一个主题对一个生成函数只启用一次。基本上,每一条消息发送都有更高的保证,并且在出现错误时不会重复

那么,如果我们已经有幂等性,那么为什么我们需要在Kafka Stream中另一个恰好一次的属性呢?幂等性和恰好一次之间有什么区别

为什么在普通Kafka制作人中不提供一次房产?

共有2个答案

阳光辉
2023-03-14

Kafka stream从端到端的角度提供了一次完全相同的语义(从一个主题消费,处理该消息,然后生成另一个主题)。但是,您只提到了生产者的幂等属性。这只是整个画面的一小部分。

让我重新表述一下这个问题:

为什么我们在消费者端需要精确一次交付语义,而我们已经在生产者端保证了精确一次交付语义?

答:因为一次交付语义不仅在生产步骤,而且在整个处理流程中。为了在语义上实现一次交货,生产和消费必须满足一定的条件。

这是一般情况:进程A向主题T生成消息。同时,进程B尝试使用来自主题T的消息。我们希望确保进程B从不两次处理一条消息。

制作人部分:我们必须确保制作人不会两次发布消息。我们可以使用Kafka幂等生产者

消费者部分:以下是消费者的基本工作流程:

  • 第1步:消费者成功地从Kafka的主题中提取消息M。
  • 第2步:消费者尝试执行作业,作业成功返回。
  • 第3步:消费者将消息的偏移量提交给Kafka代理。

以上步骤只是一条快乐的道路。现实中会出现许多问题。

  • 场景1:步骤2上的作业成功执行,但消费者崩溃。由于这种意外情况,消费者尚未提交消息的偏移量。当消费者重新启动时,消息将被消费两次

因为可能会发生很多问题,所以作业的执行和提交偏移量必须是原子的,以保证在使用者端只传递一次语义。这并不意味着我们不能,但要确保一次交付的语义准确无误,需要付出很多努力。Kafka河支持工程师的工作。

注意:Kafka流提供“一次流处理”。它指的是从一个主题消费,在Kafka主题中物化中间状态,然后产生一个主题。如果我们的应用程序依赖于其他一些外部服务(数据库、服务等),我们必须确保在这些情况下,我们的外部依赖可以保证只发生一次。

TL,DR:一次到位需要生产者和消费者之间的合作。

参考资料:

  • 精确一次语义学以及Apache Kafka是如何做到的
  • Apache Kafka中的交易
  • 仅启用一次Kafka流
卫宏硕
2023-03-14

在分布式环境中,故障是一种非常常见的情况,随时都可能发生。在Kafka环境中,代理可能会崩溃、网络故障、处理失败、发布消息失败或无法使用消息等。这些不同的场景会导致不同类型的数据丢失和复制。

故障场景

A(确认失败):生产者已成功发布消息,并重试

D(消费者在批处理消息中失败)消费者从Kafka接收一批消息,并手动提交其偏移量(enable.auto.commit=false)。如果消费者在提交Kafka之前失败,下次消费者将再次使用相同的记录,这些记录会在消费者端复制副本。

只有一次语义

在这种情况下,即使制作人尝试重新发送消息,也会导致消息被发布并被消费者消费一次。

为了在Kafka中实现精确一次语义,它使用了以下3个属性

  1. 启用。幂等性=真(地址a,b

启用幂等(Enable.idempotence=true)

幂等传递使生产者能够在单个生产者的生命周期内仅向主题的特定分区写入一次Kafka消息,而不会丢失数据和每个分区的顺序。

“请注意,启用幂等性需要MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION小于或等于5,RETRIES_CONFIG大于0,ACKS_CONFIG为‘all’。如果用户未明确设置这些值,将选择合适的值。如果设置了不兼容的值,将引发ConfigException。”

事务(隔离级别)

事务使我们能够在多个主题分区中自动更新数据。事务中包含的所有记录都将成功保存,或者不会保存任何记录。它允许您在同一事务中提交消费者补偿以及已处理的数据,从而允许端到端仅一次语义。

生产者不会等待向Kafka写入消息,而生产者使用的是起始事务、提交事务和中止事务(在失败的情况下)消费者使用isolation.levelread_committed或read_uncommitted

  • read_committed:消费者总是只读取提交的数据
  • read_uncommitted(读取未提交):按偏移顺序读取所有消息,而不等待事务提交

如果消费者与隔离。level=read_committed到达一个尚未完成的事务的控制消息时,它将不会从这个分区传递更多的消息,直到生产者提交或中止该事务,或者出现事务超时。事务超时由生产者使用配置事务确定。暂停。毫秒(默认为1分钟)。

在制片人中只有一次

在正常情况下,我们有独立的生产者和消费者。生产者必须幂等且同时管理事务,以便消费者可以使用隔离。级别为只读只读,使整个过程成为一个原子操作。这保证了制作者将始终与源系统同步。即使生产者崩溃或事务中止,它也始终是一致的,并将一条消息或一批消息作为一个单元发布一次。

同一消费者一次将收到一条消息或一批消息作为一个单元。

在一次性语义中,生产者和消费者将显示为原子操作,作为一个单元运行。要么发布并被消费一次,要么中止。

就在Kafka的小溪里

Kafka Stream使用来自主题A的消息,处理消息并将其发布到主题B,发布后使用commit(commit主要运行undercover)将所有状态存储数据刷新到磁盘。

Kafka流中只有一次是读进程写模式,它保证该操作将被视为原子操作。由于Kafka流满足了生产者、消费者和交易的需求,Kafka流就有了特殊的参数处理。保证一次或至少一次,使生活变得简单,不需要单独处理所有参数。

Kafka Streams自动更新消费者偏移量、本地状态存储、状态存储更改日志主题和生产以一起输出主题。如果这些步骤中的任何一个失败,所有更改都将回滚。

处理。保证:只需自动提供以下参数,无需明确设置

  1. 隔离。级别=读取_提交
 类似资料:
  • 我只是一个Kafka的新手,对Kafka生产者的幂等性学了一点知识。 根据我的理解,当生产者向代理发送消息时,代理需要向生产者发回一个ACK来告诉它消息已经收到。如果生产者由于某种原因没有接收到ACK,生产者必须再次向代理发送相同的消息,以便复制该消息。而幂等生成器可以消除这个问题。 基本上,每个生产者将被分配一个PID,每个消息将被分配一个序列号。所以PID+序列号可以识别一条消息。Kafka的

  • 我有一个用例,其中,我正在通过运行在EMR上的flink作业(使用flink-kinesis连接器)从kinesis流中消费事件。作业接收事件,处理它并将其接收到某个数据存储。通过处理,这里我的意思是应用一些转换(数据充实)并做聚合。我在这里有几个问题: > 如何在消耗Kinesis事件的同时保持幂等性?我想只做一次处理,因为在聚合值时,重复项可能会给出错误的结果。我能想到的一种方法是在事件中维护

  • 一、 我正试图用Kafka信源和信宿测试Flink一次语义: 运行flink应用程序,只需将消息从一个主题传输到另一个主题,并行度=1,检查点间隔20秒 每2秒使用Python脚本生成具有递增整数的消息。 使用read_committed隔离级别的控制台使用者读取输出主题。 手动杀死TaskManager 我希望在输出主题中看到单调递增的整数,而不考虑TaskManager的终止和恢复。 但实际上

  • 有没有一些更简单的方法来实现这一点呢?我本以为Liquibase能够生成这些前提条件。 谢谢

  • 我已经设置了一个Flink 1.2独立集群,其中包含2个JobManager和3个TaskManager,我正在使用JMeter通过生成Kafka消息/事件对其进行负载测试,然后处理这些消息/事件。处理作业在TaskManager上运行,通常需要大约15K个事件/秒。 作业已设置EXACTLY_ONCE检查点,并将状态和检查点持久化到Amazon S3。如果我关闭运行作业的TaskManager需

  • Apache Flink通过从检查点恢复作业,确保故障和恢复时只进行一次处理,检查点是分布式数据流和操作员状态的一致快照(分布式快照的Chandy Lamport算法)。这保证了故障切换时只需一次。 在正常集群操作的情况下,Flink如何保证只进行一次处理,例如给定一个从外部源读取的Flink源(例如Kafka),Flink如何保证从源读取一次事件?事件源和Flink源之间是否有任何类型的应用程序