Kafka如何实现精确一次语义

这篇具有很好参考价值的文章主要介绍了Kafka如何实现精确一次语义。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

kafka精确一次,kafka,java,分布式,大数据,开发语言

精确一次交付保证是关于消息传递最具争议性的话题之一,因此也是最复杂的任务之一。然而,几年前,Kafka团队宣布他们实现了这一目标,让我们深入研究一下他们的实现方式以及存在的限制。

首先,值得定义一下这些交付语义是什么。通常有三种使用的语义:

•至少一次:系统保证消息被接收,但不能保证只接收一次。•至多一次:系统不保证消息被接收,但如果接收到,则只接收一次。•精确一次:综合了前两种保证,即消息被接收且只接收一次。

当然,“精确一次”是最理想的,但同时也是最难实现的,只有在生产者、代理和消费者共同合作的情况下才可能实现。这个概念在我之前的文章中有所解释。

Kafka Streams

一个非常重要但经常被忽略的细节是,Kafka仅在Kafka Streams中支持精确一次交付。要启用它,只需将配置选项processing.guarantee从默认选项at_least_once更改为exactly_once_v2。

但是,即使在Streams应用程序中也存在限制。如果您的消费者从Kafka中读取事件并在关系型数据库中进行更改,Kafka不会回滚它。如果您的消费者发送短信通知,即使使用Kafka Streams库,Kafka也无法回滚这些通知。这些都是开发人员应始终记住的限制。

为什么要谈论“回滚”变更?这是因为处理消息的精确一次的唯一方法是在一个事务中完成。

那么,什么是Kafka Streams以及为什么可以使其具有事务性?Kafka Streams是用于构建应用程序和服务的客户端库,其中输入和输出数据存储在Kafka集群中[1]。这就是关键所在。

kafka精确一次,kafka,java,分布式,大数据,开发语言

Kafka Streams应用程序循环

Kafka Streams应用程序实现了读取-处理-写入的循环,具体步骤如下:

1.从输入主题读取消息。2.调用处理函数以处理接收到的消息,更新内部状态。3.生成输出消息并将其发送到输出主题(或多个主题)。4.等待来自Kafka的

输出消息确认。

1.提交输入主题的偏移量,表示消息已成功处理。

您可能知道,所有偏移量都存储在隐藏的Kafka主题中,Streams应用程序的内部状态也存储在名为状态存储的内部Kafka存储中。因此,所有的更改都存储在同一个Kafka集群中,并且可以在单个事务内进行管理和回滚。

kafka精确一次,kafka,java,分布式,大数据,开发语言

Streams应用程序数据存储

这里的状态存储有些过于简化,实际上更为复杂,因为它包含了日志变更主题和RocksDB实例,但我们可以在这里忽略这些细节。关于这个内部存储的更多详细信息可以在Kafka维基中找到。

幂等生产者

让我们回到开始的地方。一切可能出错的第一阶段是消息的生产。生产者将消息发送到代理并接收确认,表示代理已成功接收。如果没有接收到确认,生产者会再次发送相同的消息。

kafka精确一次,kafka,java,分布式,大数据,开发语言

Kafka生产者无法接收确认

上面的图中,您可以看到三种情况,生产者没有从代理那里接收到确认,并决定再次发送消息的情况:

1.代理没有接收到消息,因此显然没有确认。2.代理接收到了消息,但是发送确认失败。3.代理接收到了消息并成功发送了确认,但是这超过了生产者的等待超时时间。

生产者在所有这些情况下都会进行重试,但在其中两种情况(2和3)中,会导致重复。

无论是我还是Kafka的开发人员,都不知道如何解决生产者端的这个问题。因此,所有的去重工作都由代理完成,代理保证消息只会写入日志一次。为了实现这一点,消息被分配了一个序列号(我在关于幂等消费者模式的文章中描述了类似的方法)。所以,准确地说,并不是幂等的生产者,而是智能的代理完成了消息的去重工作。

要在Kafka中启用此功能,只需将生产者配置为enable.idempotence=true。

Kafka事务的工作原理

在消息被写入Kafka日志并且代理保证没有重复之后,应该在一个事务中处理消息并写入下一个主题。但是如何做到呢?

Kafka事务是写入日志的一组更改,日志本身存储在内部

Kafka主题中。此日志由一个名为事务协调器(Transaction Coordinator)的特殊实体管理。要调用事务,必须完成以下几个步骤:

1.消费者找到事务协调器。这是在应用程序启动时发生的。它将其配置的事务ID(如果存在)发送到协调器,并接收生产者ID。这在应用程序重新启动并尝试使用相同的事务ID进行注册时非常重要。当重新启动的应用程序启动新事务时,事务协调器会中止前一个实例启动的所有挂起事务。2.当应用程序消费新消息时,它启动事务。3.当应用程序将消息写入其他任何主题时,它将此信息发送给其事务协调器。协调器在其内部主题中存储有关所有更改的分区的信息。

这是一个重要的细节。使用Kafka Streams API,您不必手动将这些消息发送到协调器,Streams库将为您完成。但是,如果您直接将消息写入主题,则不会将其写入事务日志,即使此主题位于同一个集群中。

有关事务的另一个重要事项是,所有在事务期间写入的消息在事务提交之前都不会对消费者暴露。

1.事务提交或失败。如果中止,则协调器向内部主题的事务添加“中止”标记以及在事务期间写入的所有消息。2.当事务提交时,过程几乎相同。协调器向事务和所有消息添加了一个“提交”标记。该标记使得这些消息对消费者可用。

您不要忘记消费者的偏移量也存储在它们自己的主题中。这意味着提交偏移量与将消息写入输出主题相同。并且该消息也可以被标记为“中止”或“提交”,这将影响是否会再次消费相同的消息。显然,当标记为“提交”时,不会再次消费该消息;而当标记为“中止”时,整个事务将从头开始——消费消息。

事务协调器是否也是事务性的?

我尽量在文章中不过多地使用细节,以使其尽可能简单和清晰。但是还有一个值得一提的细节。事务协调器如何执行确切的事务提交?它应该更新事务、消息偏移量和输出消息,将其标记为“提交”。但是,如果在此过程中出现问题怎么办?当然,Kafka不会将一半的消息保留在已提交状态,另一半保留在挂起状态。

为了使提交更改一致,事务协调器会

首先将提交的消息写入分区协调器(Partition Coordinator)。这是另一个特殊实体,每个分区都有一个,负责维护分区的状态和偏移量。

分区协调器实现了与事务协调器相同的协议,并将消息更改存储在内部主题中。分区协调器只有在它们获得事务协调器的明确确认之后才能提交更改。否则,它们会将消息更改标记为“中止”,以便将来重试。

这种“两阶段提交”(Two-Phase Commit)的机制确保了事务的一致性。如果在提交更改之前出现问题,分区协调器不会提交更改,保持原子性。这种机制确保了Kafka的精确一次交付语义。

总结

Kafka通过结合幂等的生产者、事务和分区协调器等机制来实现精确一次交付的语义。这使得在消息的生产、处理和写入过程中能够保持一致性,并避免重复处理。

Kafka Streams提供了更简单的方式来使用精确一次交付,因为它将所有的状态和消息都存储在Kafka集群中,并利用了事务来确保处理的一致性。

然而,开发人员仍然需要注意一些限制和特殊情况,例如不能回滚外部系统的更改以及事务提交过程中的故障处理。

希望这篇文章对理解Kafka的精确一次交付机制有所帮助!文章来源地址https://www.toymoban.com/news/detail-541916.html

到了这里,关于Kafka如何实现精确一次语义的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java中如何使用消息队列实现异步(ActiveMQ,RabbitMQ,Kafka)

    在 Java 中,可以使用消息队列实现异步处理。下面是一个简单的示例代码,用于说明如何使用 ActiveMQ 实现消息队列异步处理: 添加 ActiveMQ 依赖 在 pom.xml 文件中添加以下依赖: 创建消息队列 创建一个名为 “TestQueue” 的消息队列,并配置 ActiveMQ 连接信息: 创建消息消费者

    2024年02月16日
    浏览(46)
  • flink实现kafka、doris精准一次说明

    前言说明:本文档只讨论数据源为kafka的情况实现kafka和doris的精准一次写入 flink的kafka连接器已经实现了自动提交偏移量到kafka,当flink中的数据写入成功后,flink会将这批次数据的offset提交到kafka,程序重启时,kafka中记录了当前groupId消费的offset位置,开始消费时将会从上一次

    2024年02月08日
    浏览(33)
  • JAVA面试题分享一百六十三:Kafka如何实现延时推送?

    目录 一、延时队列定义 二、技术实现方案 1. Redis 2. Kafka 3. RabbitMQ 4. RocketMQ 三、Kafka延时队列背景 四、Kafka延时队列实现思路 六、Kafka延时队列架构图 七、kafka延时任务代码实现 1. KafkaDelayQueue:Kafka延迟队列 2. KafkaDelayQueueFactory:Kafka延迟队列工厂 3. KafkaPollListener:Kafka延迟队

    2024年02月04日
    浏览(52)
  • 【软件开发/设计】分布式架构中的组件(如Kafka、MongoDB和Nginx)如何进行容器化部署

    容器化部署是将应用程序及其依赖打包成一个容器镜像,然后在任何支持容器的环境中运行这个镜像的过程。在分布式架构中,像Nginx、MongoDB、Kafka这样的组件通过容器化可以更易于部署、扩展和管理。以下是这些组件容器化部署的一般步骤和原理: 容器化部署的一般步骤

    2024年02月04日
    浏览(37)
  • 【Spring Boot+Kafka+Mysql+HBase】实现分布式优惠券后台应用系统(附源码)

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 分布式优惠券后台应用系统服务于两类用户群体,一类是商户,商户可以根据自己的实际情况即进行优惠券投放,另一类是平台消费用户,用户可以去领取商户发放的优惠券 分布式优惠券后台应用系统采用SpringBoot作为主体开

    2024年02月10日
    浏览(29)
  • Kafka-消费者-传递保证语义(Delivery guarantee semantic)

    Kafka服务端并不会记录消费者的消费位置,而是由消费者自己决定如何保存如何记录其消费的offset。 在Kafka服务端中添加了一个名为“__consumer_offsets”的内部Topic,为了便于描述简称“Offsets Topic”。 Offsets Topic可以用来保存消费者提交的offset,当出现消费者上/下线时会触发Consu

    2024年01月19日
    浏览(50)
  • 【kafka】记一次kafka磁盘空间爆满问题处理

    问题如下: 1、今天忽然出现告警,kafka某节点出现磁盘使用率超过80%告警,回顾最近操作,没有什么大业务变动,此kafka集群已经平稳运行1300多天; 2、检查集群发现,只有此节点有异常,磁盘空间消耗过度; 百度了下,然后如下方案成功解决 查看现有的__consumer_offsets清理

    2024年02月13日
    浏览(35)
  • 【kafka】记一次kafka基于linux的原生命令的使用

    环境是linux,4台机器,版本3.6,kafka安装在node 1 2 3 上,zookeeper安装在node2 3 4上。 安装好kafka,进入bin目录,可以看到有很多sh文件,是我们执行命令的基础。 启动kafka,下面的命令的后面带的配置文件的相对路径 遇到不熟悉的sh文件,直接输入名字并回车,就会提示你可用的

    2024年02月05日
    浏览(35)
  • 【分布式应用】kafka集群、Filebeat+Kafka+ELK搭建

    主要原因是由于在高并发环境下,同步请求来不及处理,请求往往会发生阻塞。比如大量的请求并发访问数据库,导致行锁表锁,最后请求线程会堆积过多,从而触发 too many connection 错误,引发雪崩效应。 我们使用消息队列,通过异步处理请求,从而缓解系统的压力。消息队

    2024年02月16日
    浏览(28)
  • 大数据之Kafka————java来实现kafka相关操作

    一、在java中配置pom 二、生产者方法 (1)、Producer Java中写在生产者输入内容在kafka中可以让消费者提取 [root@kb144 config]# kafka-console-consumer.sh --bootstrap-server 192.168.153.144:9092 --topic kb22 (2)、Producer进行多线程操作   生产者多线程是一种常见的技术实践,可以提高消息生产的并发性

    2024年02月11日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包